【问题标题】:Why doesn't C++ allow two function/class templates with the same name, differing only by the type of a non-type template parameter (of integral type)?为什么 C++ 不允许两个具有相同名称的函数/类模板,仅在非类型模板参数(整数类型)的类型上有所不同?
【发布时间】:2018-09-02 12:31:52
【问题描述】:

当我尝试这个时,编译器会出错。我尝试了 VC++ 和 g++。

这同样适用于函数模板和类模板(尽管对于函数模板,编译器错误仅在函数模板被实例化时发生;类模板的编译器错误在编译器遇到第二个类定义时立即发生)。

这里是一个函数模板的例子:

template <unsigned int>
void Foo() {}

template <signed int>    // Same name, only difference is the type of the
void Foo() {}            // non-type template parameter (of integral type)

Foo<10U>(); // COMPILER ERROR.

上面,为什么编译器不能只实例化Foo&lt;unsigned int&gt;()

我发现如果模板函数/类的第二个版本具有类型模板参数,这不是问题。如果模板函数/类的第二个版本具有 non-integral 类型的非类型模板参数,这也不是问题:

template <unsigned int>
void Foo() {}

template <unsigned int*>  // Non-type template parameter
void Foo() {}             // of non-integral type

template <typename T>     // Type template parameter
void Foo() {}


Foo<10U>();               // OK

所以如果我不得不猜测我会说这与编译器可以在整数类型的值之间进行转换这一事实有关吗?但这并不能阻止 C++ 允许两个仅在整数参数类型上有所不同的重载函数。

【问题讨论】:

  • 如果您使用特定类型,模板的意义何在?
  • 将第二个版本更改为template &lt;signed int I, std::enable_if_t&lt;(I &lt; 0)&gt;* = nullptr&gt; 将使其工作。 (正数选择无符号版本,负数选择有符号版本)
  • 非常感谢,使用 SFINAE 可能会帮助我完成我想要完成的工作。虽然这个问题主要是关于为什么 C++ 的行为方式。
  • Sagi,模板可以具有非类型模板参数,根据定义,这些参数属于具体类型。这在许多不同方面都很有用,这就是该语言包含该功能的原因。

标签: c++


【解决方案1】:

确实允许,您可以很好地编写两个模板。它们只是在实例化时变得不可用。原因是没有“重载分辨率”来选择模板。对非类型模板参数的唯一要求如下:

[temp.arg.nontype]/2

非类型模板参数的模板参数应该是 模板参数类型的转换常量表达式。

10uintunsigned int 类型的转换常量表达式。可作为任一重载的参数。

【讨论】:

  • 感谢 StoryTeller,这对我有帮助,并且主要回答了我心中的问题。您引用的摘录使得无法定义/实例化两个仅通过整数类型的非类型模板参数不同的模板,因为用于实例化的模板参数必须转换为参数类型。因此,这两个版本变得无法区分。所以这就是编译器强制执行此行为的原因,但我仍然不确定 why spec 强制执行此行为(通过您引用的摘录)但也许答案会出来我的深度......
猜你喜欢
  • 2014-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-12
  • 2019-12-18
  • 1970-01-01
  • 1970-01-01
  • 2011-07-30
相关资源
最近更新 更多