Nontype template parameter generated with decltype function for function

I want to replace the signature signature with decltype and found out that it doesn't compile with most compilers. Is this a new feature, or perhaps unspecified behavior?

#include <iostream>

template <typename T, T nontype>
struct CL {
    void call() { nontype(123); }
};

void f(int n) {
    std::cout << n << std::endl;
}
CL<void(*)(int), f> cl7;

using df = decltype(f);
CL<df, f> cl8; // << error

int main() {
    cl8.call();
}

      

so (not really sure about the compiler versions):

clang - 3.4 http://rextester.com/UOIV91915

compiles, runs, produces output

g ++ 4.9+ http://coliru.stacked-crooked.com/a/dbec1e202c48fd81

main.cpp:14:9: error: 'void(int)' is not a valid type for a template non-type parameter
 CL<df, f> cl8; // << error
         ^
main.cpp:14:14: error: invalid type in declaration before ';' token
 CL<df, f> cl8; // << error
              ^
main.cpp: In function 'int main()':
main.cpp:17:6: error: request for member 'call' in 'cl8', which is of non-class type 'int'
  cl8.call();

      

Visual Studio 2013 Update 4

fatal error C1001: An internal error has occurred in the compiler.

      

+3


source to share


1 answer


Non-standard template parameters cannot be of function type. They can have a pointer to a function type, and there is a paragraph in the standard that somehow means your code is correct - [temp.param] / 8:

A non-standard template parameter of type "array T

" or "function return T

" is configured as "pointer to T

" or "pointer to function returns T

", respectively.

However, it is unclear if this is done after replacing the template or before it, which is covered in this defect report . It's easy to fix it just to write

using df = decltype(&f);

      

Demo .




Why does it work using df = decltype((f));

?

[dcl.type.simple] / 4:

For an expression, the e

type denoted by a symbol decltype(e)

is defined as follows:

  • if e

    is an unparenthesized id-expression or unbound class member access (5.2.5), decltype(e)

    is the type of object named e

    . If no such object is present, or if e names a set of overloaded functions, the program is ill-formed;
  • otherwise, if e

    is the value of x, decltype(e)

    is T&&

    where T

    is the type e

    ;
  • otherwise , if e

    is an lvalue, decltype(e)

    is T&

    where T

    is the type e

    ;
  • otherwise, it decltype(e)

    is the type e

    .

(f)

is enclosed in parentheses and an lvalue, so it decltype((f))

is an lvalue reference to f

the function type - void(&)(int)

. Template parameters can be referenced to the function type, so it works. However, since this fact is rather controversial (and not so well known), it decltype(&f)

should be less annoying in your code.

+5


source







All Articles