4

I have some macros which operate on types and initial values. I need to cast the initial value vIni to the vType (vIni is always convertible to vType, sometimes it has the same type). The vIni might be empty as well, in which case vType should be uninitialized or default-initialized. The reult is passed to templated function.

In short,

template<typename T> void foo(const T& o);

foo(vType(vIni));
foo(vType());

must compile.

I already discovered that foo(unsigned int()) or foo(int*()) will not compile, but it can be worked around with a typedef.

What are other cases (besides built-in types with spaces and pointers) which will fail?

Nick
  • 25,026
  • 7
  • 51
  • 83
eudoxos
  • 18,545
  • 10
  • 61
  • 110
  • Obviously, `void()`, but that's got more to do with the fact that you can't have `void` objects than the precise syntax. – MSalters May 10 '12 at 12:31
  • Possible duplicate of http://stackoverflow.com/questions/4669131/how-to-check-if-a-template-argument-is-default-constructible, also cf. http://en.cppreference.com/w/cpp/types/is_default_constructible – Christopher Creutzig May 10 '12 at 14:05
  • @ChristopherCreutzig: that's not what this question is about as far as I can tell. This isn't really about the type itself, it's about how the type is named (hence, "can be worked around with a typedef"). Certainly the answer to that supposed dupe doesn't answer this question at all. – Steve Jessop May 10 '12 at 14:21

1 Answers1

5

The short (slightly over-simplified) answer is, "it will fail for anything other than a simple-type-specifier".

5.2.3/1 says:

A simple-type-specifier (7.1.6.2) or typename-specifier (14.6) followed by a parenthesized expression-list constructs a value of the specified type given the expression list.

A simple-type-specifier can be either a one-word name for a type (optionally plus some :: stuff for the scope, and/or template arguments which themselves need not be simple type specifiers) or a decltype expression. The possibilities are listed in 7.1.6.2.

unsigned int and int* aren't simple-type-specifiers. Any compound type specifier will fail, so cv-qualification, array types, function types, pointer types including pointer-to-function and pointer-to-member would all need a typedef.

Also ruled out are the multi-word type identifiers like unsigned char, long double. For your first example, unsigned would work in place of unsigned int.

A typename-specifier is a type preceded by typename, used in templates to assert that a dependent name is indeed a type, not a data member or member function.

Finally of course, once you get past this restriction the type has to actually be constructible or convertible from the expression-list. So for example you can't create a temporary of function type using this or any other syntax.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • Surprisingly enough, template compound types do work: `std::vector()`. Per 7.1.6.2, a _simple-template-id_ is a _simple-type-specifier_ – MSalters May 10 '12 at 13:15
  • 1
    People often create an alias or identit type for such uses, i.e., `alias::type()` – Puppy May 10 '12 at 13:55
  • @DeadMG: yep, that's better than my thing involving `declspec`. – Steve Jessop May 10 '12 at 13:59
  • Note that you also cannot create a temporary array without such an `alias`. :) `auto&& arr = alias{1, 2, 3};` – Xeo May 10 '12 at 14:26