c++ - 所有版本的 GCC 都在使用在定义中具有默认类型的模板

标签 c++ c++11 templates gcc

我浪费了无数个小时来查明 gcc 的问题。我想用另一个编译器测试我们的代码库,以寻找更多 Clang 的警告。可能错过了。令我震惊的是,由于模板参数推导失败,几乎一半的项目停止编译。在这里,我试图将我的案例简化为最简单的代码。

#include <type_traits>

struct Foo
{ };

// This is a template function declaration, where second template argument declared without a default
template <typename T, typename>
void foo(const Foo & foo, T t);

// This is a template function definition; second template argument now has a default declared
template <typename T, typename = typename std::enable_if<1>::type>
void foo(const Foo & foo, T t)
{
}

int main(int argc, char ** argv)
{
    foo(Foo{}, 1);
    return 0;
}

忽略 1std::enable_if<1> .显然,它是一个常数值,只是为了在无关紧要的情况下不使事情复杂化。

这段代码编译[1]使用 clang(3.4 到 4.0)、icc(16、17)、Visual C++(19.00.23506)。基本上,我找不到任何其他 c++11 编译器,除了 gcc(4.8 到 7.1),不编译这段代码。

问题是,这里谁对谁错? gcc 是否符合标准?

显然这不是一个关键问题。我可以轻松移动std::enable_if到声明。唯一的受害者将是美学。但是能够隐藏一个丑陋的 100 个字符长度是很好的 std::enable_if在实现中与库函数的用户没有直接关系的一段代码。


godbolt.org 上的实时示例.

最佳答案

标准内容([1] 第 350 页):

The set of default template-arguments available for use with a template declaration or definition is obtained by merging the default arguments from the definition (if in scope) and all declarations in scope in the same way default function arguments are (8.3.6). [ Example:

template<class T1, class T2 = int> class A;
template<class T1 = int, class T2> class A;
is equivalent to
template<class T1 = int, class T2 = int> class A;

— end example ]

所以 GCC 在这里是错误的。它会忽略声明中的默认模板参数。

不是所有的声明,只有函数模板声明。类模板声明没问题:

#include <type_traits>

template <typename T, typename>
struct Foo;

template <typename T, typename = typename std::enable_if<1>::type>
struct Foo
{
    T t;
};

int main()
{
    Foo<int> foo;
    return 0;
}

godbolt.org 上的实时示例


这可能是由于非默认参数的推断方式的性质。在函数模板中,它们是从函数参数中扣除的。在类模板中,我们必须明确指定它们。

不管怎样,我已经创建了一个 bug report .

关于c++ - 所有版本的 GCC 都在使用在定义中具有默认类型的模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43993162/

相关文章:

c++ - 不可复制、不可移动、显式构造类型的成员数组的初始化

java - 如何将抽象 Number 初始化为 0?

c++ - 将流存储在变量中供以后使用

c++ - 如何使用 Boost 实现 C++14 风格的自动返回类型?

c++ - 将 C++ 函数名称打印到 C 而不进行修饰

c++ - 在性能方面,生成随机书籍的最佳方法是什么?

c++ - 类初始值设定项检查特定输入

c++ - 为什么最大两个字符串文字的输出是错误的?

c++ - 混合模板、多重继承和非默认构造函数

c++ - 合并指针