【问题标题】:using declaration: one more bug of gcc and clang?使用声明:gcc 和 clang 的另一个错误?
【发布时间】:2019-12-28 22:41:19
【问题描述】:

为什么gcc HEAD 10.0.0 20190Clang HEAD 9.0.0 都拒绝这个程序?

#include <iostream>

void g( int x )
{
    std::cout << "Hello g( " << x  << " )\n";
}

template <int N>
void g()
{
    std::cout << "Hello g<N>( " << N  << " )\n";
}

namespace N
{
    using ::g;
}

void g( int x = 20 );

template <int N = 10>
void g();

int main()
{
    N::g();
    N::g<>();
}

例如gcc 发出错误

prog.cc: In function 'int main()':
prog.cc:27:11: error: no matching function for call to 'g()'
   27 |    N::g<>();
      |           ^
prog.cc:9:6: note: candidate: 'template<int N> void g()'
    9 | void g()
      |      ^
prog.cc:9:6: note:   template argument deduction/substitution failed:
prog.cc:27:11: note:   couldn't deduce template parameter 'N'
   27 |    N::g<>();
      |           ^

尽管根据 C++ 20(和 17)标准(9.8 使用声明)

11 [注意:对于嵌套名称说明符命名为 命名空间,在 using 声明之后添加到命名空间的成员 不在引入的声明集中,所以它们不在 在使用名称时考虑。因此,额外的重载 在 using-declaration 之后添加被忽略,但默认功能 参数 (9.2.3.6)、默认模板参数 (13.1) 和模板 考虑专业化(13.6.5、13.8.3)。 ——尾注]

根据我对标准的阅读,我认为这是一个错误。

【问题讨论】:

  • Clang 确实做了同样的事情:godbolt.org/z/Rt_FLy
  • @MaxLanghof 我自己已经测试过了。:)
  • 那么我很困惑为什么这个问题特别与 gcc 有关。如果它是 gcc 中的错误,那么它也是 clang 中的错误...
  • @VladfromMoscow MaxLanghof 的观点是它在 gcc 和 clang 的 HEAD 中导致相同的错误。因此,如果 gcc 中的错误消息是错误,那么 clang 中的相同错误消息也必须是错误。如果你有一个适用的 clang 版本,那么你应该告诉它是哪个版本(提交)。
  • @VladfromMoscow 没有人说两者会/总是表现相同。但是 this 代码在 clang 和 gcc 中产生了同样的错误(当前 HEAD 在编写该注释时)。问题更多的是您为什么要专门询问编译器而不是language-lawyer 问题或类似的问题。并提到它不会在 gcc(和 clang)中编译,即使您希望它应该编译。

标签: c++ language-lawyer c++17 using-declaration


【解决方案1】:

此问题是Core issue 1907 的主题。目前的方向是将此类病例视为病态,无需诊断。

事实证明,一些实现在“每个实体”的基础上跟踪默认参数(因此很难不考虑在以后的重新声明中添加默认参数),而其他实现则在“每个声明”上跟踪它们基础(因此很难让他们考虑这样的默认参数)。 CWG 决定通过对依赖于 IFNDR 的代码进行分类来适应这两种实施策略。

【讨论】:

  • 我看到日期日期:2014-03-30。但是我提供了一份 C++ 20 标准草案的报价。
  • 是的,起草和批准修复缺陷的措辞需要时间。特别是如果有更高优先级的项目,如实际功能。
【解决方案2】:

我认为问题在于您在定义期间隐式声明 g&lt;int&gt; 模板函数后重新声明它。

这个最小化的例子也无法编译。注意不涉及命名空间:

#include <iostream>

template <int N>
void g()
{
    std::cout << "Hello g<N>( " << N  << " )\n";
}

// redeclaration    
template <int N = 10>
void g();


int main()
{
    g<>();
}

而这是编译:

#include <iostream>


// declaration
template <int N = 10>
void g();

// definition
template <int N>
void g()
{
    std::cout << "Hello g<N>( " << N  << " )\n";
}


int main()
{
    g<>();
}

【讨论】:

  • 这与我指出的 C++ 标准中的引用毫无共同之处。
  • @vlad 但它与您在问题中的代码有很多共同点。如果它在没有 using 命名空间的情况下是不正确的,那么它在 using 命名空间中仍然如此。格式错误的程序中的 an.error 的文本在标准下没有任何限制。
  • @Yakk-AdamNevraumont 我确信这是一个错误的类比。关于编译器行为与 using 声明相关的问题。
  • @vlad 是的,但是如果没有 using 声明的代码格式不正确,添加 using 声明后仍然是格式错误,并且不更改示例无法得出关于添加 using 声明的结论。
  • @Yakk-AdamNevraumont 不,没有 using 声明的代码不是格式错误的。阅读 C++ 标准。
猜你喜欢
  • 2017-11-27
  • 1970-01-01
  • 2016-04-07
  • 2020-11-26
  • 2010-11-23
  • 1970-01-01
  • 2016-07-04
  • 2023-03-29
  • 1970-01-01
相关资源
最近更新 更多