我有以下代码:
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;
}
为什么是 A<(const char *)(&i)> a;
是错的?我用 g++-4.6.1 和 -std=c++0x 编译它。
编辑:正如查尔斯建议的 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*’
因此,不仅reinterpret_cast
不被允许。使用 A<static_cast<const base*>(&derived)
产生同样的错误。
致@BЈовић:
A<(const Base*)(0)> b; // error: could not convert template argument ‘0u’ to ‘const Base*’
最佳答案
至于“标准如此”的答案,请看评论。
真正的问题是为什么不允许这样做?
在模板参数中断然拒绝类型转换是很有意义的,因为您真正感兴趣的是模板参数的值。 然而,类型转换可能会变得任意复杂,并且不会被强制为 constexpr
s。标准(显然)根本不会对内置(原始)类型进行异常(exception)处理。
请注意,您的 E<(int)f>
示例也被 clang
驳斥原因:
error: non-type template argument of type 'int' is not an integral constant expression
为什么 gcc 允许这样做是可疑的,但我认为它允许您使用 constexpr
s 你可以明确声明。请注意,这是不可能偷偷i
的地址的。 A
的参数列表中.
关于c++ - 为什么指针类型转换不适用于模板非类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12137840/