【问题标题】:Clang doesn't compile code but gcc and msvc compiled itClang 不编译代码,但 gcc 和 msvc 编译了它
【发布时间】:2020-06-03 19:02:12
【问题描述】:

我不明白问题出在哪里:无论是在我的代码中还是在编译器中(不太可能)。有一段代码是这样的:

#include <iostream>
#include <type_traits>
#include <set>


template<typename T, typename = void>
struct TestA: std::false_type {};

template<typename T>
struct TestA<T, std::void_t<typename T::reverse_iterator>> : std::true_type {};

template<typename T>
struct TestA<T, std::void_t<typename T::dummy_iterator>> : std::true_type {};

int main()
{
    std::cout << TestA<std::set<int>>::value;
}

GCC 和 MSVC 都编译它。我使用不同版本的 GCC 和 MSVC 17(本地)和 19 在 Godbolt 上对其进行了测试。这是一个链接:https://godbolt.org/z/Enfm6L

但是 Clang 没有编译它并发出错误:

redefinition of `'TestA<T, std::void_t<typename T::dummy_iterator> >'`

我很感兴趣 - 也许标准的某些部分中这段代码不正确,或者可能是其他原因。

【问题讨论】:

  • "std::set::reverse_iterator""std::set::dummy_iterator" 在 clang 头文件中是如何定义的?跨度>
  • std::set::dummy_iterator 根本没有在 clang 头文件中定义(我希望)。您可以将 dummy_iterator 更改为您想要的任何内容,它不会改变结果,因为问题不在定义中,如下所示。
  • 谢谢安德烈,我看了答案,确实很有趣

标签: c++ templates gcc visual-c++ clang


【解决方案1】:

这很可能与CWG 1558有关。

别名模板特化中未使用参数的处理 17.6.7 [temp.alias] 的当前措辞未指定。为了 示例:

  #include <iostream>

  template <class T, class...>
    using first_of = T;

  template <class T>
    first_of<void, typename T::type> f(int)
      { std::cout << "1\n"; }

  template <class T>
    void f(...)
      { std::cout << "2\n"; }

  struct X { typedef void type; };

  int main() {
    f<X>(0);
    f<int>(0);
  }

是对 first_of 的引用,其中 T 为 int 相当于简单的void,还是替换失败?

这是一个自已解决的缺陷,但如果您使用的 Clang 版本尚未实现修复,它可能仍然认为这两种专业化只是将第二个参数定义为 void,而不是进行整个替换失败的咒语。解决方法是不要使用普通别名 std::void_t,而是使用稍微复杂的版本

template <typename...> struct voider { using type = void; };
template <typename... T> using my_void_t = typename voider<T...>::type;

对于类模板(这是别名现在所代表的),定义了替换失败。将其插入您的示例可以安抚 Clang https://godbolt.org/z/VnkwsM

【讨论】:

  • 另一种解决方法是为每个需求创建特征,然后将它们组合在 enable_ifstd::disjunction(或 requires 子句)中
  • 感谢您的帮助和参考!很遗憾听到 Clang 中出现这种错误。不过,有趣的是,我认为您的 void_t 实现是标准的。不能采用模板别名的思想。
猜你喜欢
  • 1970-01-01
  • 2022-10-12
  • 1970-01-01
  • 1970-01-01
  • 2017-10-17
  • 2022-10-18
  • 1970-01-01
  • 1970-01-01
  • 2022-09-28
相关资源
最近更新 更多