【问题标题】:Template specialization with type conversion具有类型转换的模板特化
【发布时间】:2013-09-22 06:27:07
【问题描述】:

我发现了这段假代码(下面是人为的例子):

template <int I, typename T>
struct foo
{
    static int bar()
    {
        return 1;
    }
};

template <std::size_t Index, typename T>
struct foo<Index, T*>
{
    static int bar()
    {
        return 2;
    }
};

请注意,专业化使用不同的类型(错误地)。令人惊讶的是,它在 GCC 4.8.1 和 Clang 3.4 中编译时没有任何错误(或警告)。但更奇怪的是 GCC 行 foo&lt;0, int*&gt;::bar() 结果为 1,但 Clang 给出了 2。到底是怎么回事?它仍然被标准视为专业化吗?

【问题讨论】:

  • 特化 size_t 应该是一个错误 (int != size_t)
  • 所以两个编译器都错了?听起来很……不太可能;-)
  • 你们为什么认为这是一个专业化?
  • @ruslo 可能是我错了。我在阅读问题时遗漏了部分代码。
  • 我怀疑:std::size_tint 可能仅在函数参数的情况下被视为不同的类型,而不是模板参数?

标签: c++ templates gcc clang template-specialization


【解决方案1】:

Gcc 是错误的,因为你根本不能调用这个专业化。 只需删除主模板定义:

template <int I, typename T>
struct foo;

template <std::size_t Index>
struct foo<Index, int*> {
  static int bar() {
    return 2;
  }
};

int main() {
  std::cout << foo<std::size_t(0), int*>::bar() << std::endl; // nope, not work
  std::cout << foo<0, int*>::bar() << std::endl; // nope, not work
}

观看直播example。并且this 代码必须报告模棱两可的部分专业化,但它不是(对于 gcc)。 Clang report“模棱两可”。

PS 我认为,这部分没有被标准覆盖。

更新

在这种情况下,clang 不适用于 枚举example

【讨论】:

  • 我几乎可以肯定这是一个 GCC 错误,我稍后会填写错误报告。同时,我认为我应该接受您的回答 :-) 我会及时通知您
【解决方案2】:

在非类型模板参数上部分特化类模板的限制 14.5.5 [temp.class.spec] 第 8 段列出了以下限制:

部分特化的非类型实参表达式不应包含部分特化的模板形参,除非实参表达式是简单标识符。

使用size_t 的参数表达式涉及到int 的转换(size_t 是无符号的),因此不是一个简单的标识符。

【讨论】:

  • @ruslo:它看起来确实是一个简单的标识符,但实际上是int(Index),这似乎不再是一个简单的标识符了。
  • @ruslo:这对于标识符可能是正确的,但限制清楚地讨论了表达式,并且必须成为int(Index),因为标识符标识的实体类型是std::size_t,这是有保证的不要成为int
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-30
  • 2014-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多