13

我有以下代码:

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*’
4

1 回答 1

4

至于“标准这么说”的答案,请看评论。

真正的问题是为什么不允许这样做?

在模板参数中断然拒绝类型转换很有意义,因为您真正感兴趣的是模板参数的值。然而,类型转换可能会变得任意复杂,并且不会强制为constexprs。标准(显然)根本不会对内置(原始)类型进行例外处理。

请注意,您的E<(int)f>示例也被clang以下原因驳斥:

错误:“int”类型的非类型模板参数不是整数常量表达式

为什么 gcc 允许这样做是可疑的,但我认为它允许您使用constexpr可以显式声明的 s 。请注意,这不可能i在 的参数列表中偷偷摸摸 的地址A

于 2012-08-27T09:39:13.957 回答