Topic: std::is_literal type traits should be provided


Author: =?iso-8859-1?q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Sat, 25 Aug 2007 09:34:33 CST
Raw View
Since the inclusion of constexpr in the standard draft N2369 we have
a new type category "literal", which is defined in [basic.types]/p.
11:

"A type is a literal type if it is:
- a scalar type; or
- a class type (clause 9) with
  - a trivial copy constructor,
  - a trivial destructor,
  - at least one constexpr constructor other than the copy
constructor,
  - no virtual base classes, and
  - all non-static data members and base classes of literal types; or
- an array of literal type."

I strongly suggest that the standard provides a type traits for
literal
types in [meta.unary.prop] for several reasons:

a) To keep the traits in sync with existing types.
b) I see many reasons for programmers to use this trait in template
   code to provide optimized template definitions for these types,
   see below.
c) A user-provided definition of this trait is practically impossible
to
    write portably.

The special problem of reason (c) is that I don't see currently a
way to portably test the condition for literal class types:

"- at least one constexpr constructor other than the copy
   constructor"

Here follows a simply example to demonstrate it's usefulness:

template <typename T>
constexpr std::enable_if<std::is_literal<T>::value, T>::type
abs(T x) {
  return x < T() ? -x : x;
}

template <typename T>
std::enable_if<!std::is_literal<T>::value, T>::type
abs(const T& x) {
  return x < T() ? -x : x;
}

Here we have the possibility to provide a general abs function
template that can be used in ICE's if it's argument is a literal
type which's value is a constant expression, otherwise we
have an optimized version for arguments which are expensive
to copy and therefore need the usage of arguments of
reference type (instead of const T& we could decide to
use T&&, but that is another issue).

Proposed resolution:

In [meta.type.synop] in the group "[20.4.4.3] type properties",
just below the line

template <class T> struct is_pod;

add a new one:

template <class T> struct is_literal;

In [meta.unary.prop], table Type Property Predicates, just
below the line for the is_pod property add a new line:

column "Template":
template <class T>
struct is_literal;

column "Condition":
T is a literal type (3.9)

column "Preconditions":
T shall be a complete type, an
array of unknown bound, or
(possibly cv-qualified) void.

Greetings from Bremen,

Daniel Kr   gler


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?iso-8859-1?q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Sat, 25 Aug 2007 20:12:27 CST
Raw View
On 25 Aug., 17:34, Daniel Kr   gler <daniel.krueg...@googlemail.com>
wrote:
> template <typename T>
> constexpr std::enable_if<std::is_literal<T>::value, T>::type
> abs(T x) {
>   return x < T() ? -x : x;
>
> }
>
> template <typename T>
> std::enable_if<!std::is_literal<T>::value, T>::type
> abs(const T& x) {
>   return x < T() ? -x : x;
>
> }

I shamelessly omitted the required typenames (I wrote too much
concepts code ;-)), so please read them as:

emplate <typename T>
constexpr typename std::enable_if<std::is_literal<T>::value, T>::type
abs(T x) {
  return x < T() ? -x : x;
}

template <typename T>
typename std::enable_if<!std::is_literal<T>::value, T>::type
abs(const T& x) {
  return x < T() ? -x : x;
}

With apologies,

Daniel Kr   gler


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]