gpt4 book ai didi

c++ - C++ 17 中 Clang 的不明确部分特化

转载 作者:IT老高 更新时间:2023-10-28 23:20:48 27 4
gpt4 key购买 nike

template <typename Foo, Foo Part>
struct TSelect {};

enum What {
The
};

template <typename Foo>
struct AnotherOneSelector {
static constexpr Foo Id = Foo::The;
};

template <typename Foo, typename SelectPartType>
struct THelper;

template <typename Foo>
struct THelper<Foo, TSelect<Foo, AnotherOneSelector<Foo>::Id>> {};

template <typename Foo, Foo PartId>
struct THelper<Foo, TSelect<Foo, PartId>> {};

int main() {
THelper<What, TSelect<What, What::The>> t;
}

此代码使用 gcc8.1 编译每个标准选项(c++11、c++14、c++17),但 clang trunk 不使用 c++17 (虽然 c++14 一切都很好)。

消息错误是:

test.cpp:23:49: error: ambiguous partial specializations of 'THelper<What, TSelect<What, The> >'
THelper<What, TSelect<What, What::The>> t;
^
test.cpp:17:12: note: partial specialization matches [with Foo = What]
struct THelper<Foo, TSelect<Foo, AnotherOneSelector<Foo>::Id>> {};
^
test.cpp:20:12: note: partial specialization matches [with Foo = What, PartId = The]
struct THelper<Foo, TSelect<Foo, PartId>> {};
^
1 error generated.

哪个编译器是正确的?我没有看到模板有任何变化专攻 C++17。

最佳答案

这里的 C++17 不同之处在于可以从对应的实参推导出非类型形参的类型。而 Clang 显然做错了推论。

与此处相关,您应该为 Foo 合成一个唯一类型并尝试推导出 FooPartIdTHelper<Foo, TSelect<Foo, PartId>>反对THelper<Unique, TSelect<Unique, AnotherOneSelector<Unique>::Id>> .似乎正在发生的是 Clang 对待 AnotherOneSelector<Unique>::Id有一些单独的独特类型 - 称之为 Unique2 - 因此在 C++17 中推导失败,因为您推导了 Foo 的冲突类型.众所周知,像这样的非推导上下文的处理没有明确说明,但我很确定它是为了使用转换后的模板参数的类型而不是原始类型来推导。

两种可能的解决方法是:

  • 禁止扣除Foo通过将类型包装到非推导上下文中来从非类型参数中提取。例如:template <typename Foo, std::remove_const_t<Foo> PartId> .
  • 强制转换为 Foo在模板参数中以避免虚假冲突:struct THelper<Foo, TSelect<Foo, Foo{AnotherOneSelector<Foo>::Id}>>

关于c++ - C++ 17 中 Clang 的不明确部分特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51126940/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com