繁体   English   中英

使用C ++中的Clang进行模糊的部分特化17

[英]Ambiguous partial specializations with Clang in C++17

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合成一个唯一的类型,并尝试推导出THelper<Foo, TSelect<Foo, PartId>>中的FooPartId ,而THelper<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}>>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM