I have the following code:
template <const char *p>
struct A{};
template <int i>
struct E{};
extern constexpr int i = 0;
constexpr float f = 0.f;
extern constexpr char c = 0;
int main(int argc, const char *argv[])
{
A<&c> b; //works
A<(const char *)(&i)> a; //Error: could not convert template argument ‘(const char*)(& i)’ to ‘const char*’
E<(int)f> e; //works
return 0;
}
why the line A<(const char *)(&i)> a;
is wrong? I compiled it with g++-4.6.1 with -std=c++0x.
EDIT: As Charles suggested that reinterpret_cast
is not permitted in a constant expression, I change the above code to the following:
struct Base{};
struct Derived : public Base {};
template <const Base *p>
struct A{};
extern constexpr Base base = {};
extern constexpr Derived derived = {};
A<&base> a; //works
A<(const Base*)&derived> b; //error: could not convert template argument ‘(const Base*)(& derived)’ to ‘const Base*’
Therefore, not only reinterpret_cast
is not allowed. Using A<static_cast<const base*>(&derived)
yields the same error.
To @BЈовић:
A<(const Base*)(0)> b; // error: could not convert template argument ‘0u’ to ‘const Base*’
As for "the standard says so" answers, look in the comments.
The real question is Why would this not be allowed?
It makes a lot of sense to categorically refuse type conversions in template arguments, because what you are really interested in is the value of the template argument. Type conversions however can become arbitrarily complicated and are not forced to be constexpr
s. The standard (apparently) simply doesn't make an exception for built-in (primitive) types.
Note that your E<(int)f>
example is also refuted by clang
with the reason:
error: non-type template argument of type 'int' is not an integral constant expression
Why gcc allows this is dubious, but I'd assume it allows you to use constexpr
s that you could explicitly declare. Note that this is not possible to sneak the address of i
in the parameter list of A
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With