Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Templates with constexpr function returns as arguments

Given some declarations:

template <class T, T t>
struct foo {};

template <class T>
constexpr T ident(T t) {
   return t;
}

constexpr int bar() {
   return 0;
}

int main(int argc, const char *argv[])
{
    foo<bool, true> a;
    foo<int, bar()> b;
    foo<int, ident(0)> c;
    foo<int (*)(), bar> d;

    foo<int(*)(), ident(&bar)> e; // not accepted (gcc 4.7.2 crashes here, even)

    return 0;
}

Aside: Interestingly enough, this caused a segfault on gcc 4.7.2. I had to run it through my svn build of a 4.8.0 snapshot to even get an error message ("must be address of function with external linkage")...

Why are the first OK, and the last disallowed - isn't this constexpr like cases a-d? It seems like the compiler is perfectly capable of determining which function ident(&bar) is talking about, since it can do it for other types.

like image 433
Robert Mason Avatar asked Oct 26 '25 08:10

Robert Mason


2 Answers

This will be permitted from C++17 onwards; see N4198 (and the corresponding wording paper N4268 that was recently voted into the C++ standard). Clang trunk accepts your code in -std=c++1z mode.

like image 53
Richard Smith Avatar answered Oct 27 '25 23:10

Richard Smith


The problem with E is that for a non-type template parameter, of type pointer-to-function, it must be valid to take the address of it (14.3.2). For example, foo<int(*)(), &ident(bar)> is not valid. So even though the return of ident(bar) is a pointer to a function with valid external linkage, the expression as a whole is not valid, for a non-type template parameter. If you had returned 0 (or nullptr) from ident(bar), it would of compiled (also defined in 14.3.2).

The standard allows you to omit the & on a type of pointer to function, but it still must be valid to take the address of it. This is why foo<int (*)(), bar> works, because foo<int (*)(), &bar> is valid. The other function calls for B, C (and A) evaluate to integer constants, which falls into different category.

like image 35
capsterx Avatar answered Oct 27 '25 22:10

capsterx