Dan*_*ang 13 c++ templates c++11
我有以下代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
为什么这条线A<(const char *)(&i)> a;错了?我用g ++ - 4.6.1用-std = c ++ 0x编译它.
编辑:正如Charles建议reinterpret_cast在常量表达式中不允许的那样,我将上面的代码更改为以下代码:
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*’
Run Code Online (Sandbox Code Playgroud)
因此,不仅reinterpret_cast是不允许的.使用A<static_cast<const base*>(&derived)产生相同的错误.
致@BЈовић:
A<(const Base*)(0)> b; // error: could not convert template argument ‘0u’ to ‘const Base*’
Run Code Online (Sandbox Code Playgroud)
至于“标准是这么说的”答案,请查看评论。
真正的问题是为什么不允许这样做?
明确拒绝模板参数中的类型转换很有意义,因为您真正感兴趣的是模板参数的值。然而,类型转换可以变得任意复杂,并且不必强制constexpr转换。标准(显然)根本没有对内置(原始)类型做出例外。
请注意,您的E<(int)f>示例也被驳斥,clang原因如下:
错误:“int”类型的非类型模板参数不是整型常量表达式
为什么 gcc 允许这样做是值得怀疑的,但我假设它允许您使用constexpr可以显式声明的 s。请注意,这是不可能将 的地址隐藏i在 的参数列表中的A。