C++20概念:越界定义在MSVC中失败,但在GCC或clang中失败



考虑一下这个小代码片段

namespace nsp
{
template<typename T>
concept Addable= requires(const T& a,const T& b)
{
{a + b} -> std::convertible_to<T>;
};
template<Addable T>
struct C
{
C();
};
}
template<nsp::Addable T>
nsp::C<T>::C() {};

如图所示,GCC(10.2(和clang(11.0(接受代码,而MSVC(x86 19.28(拒绝代码并返回错误消息:

error C3855: 'nsp::C<T>': template parameter 'T' is incompatible with the declaration. 

这是MSVC的错误还是GCC和clang接受它是错误的?或者,我做了什么愚蠢的事吗?如果我将越界的定义移到名称空间nsp中,它似乎也适用于MSVC。请参见此示例。

这种行为是MSVC中可观察到的偏差,通常在模板和SFINAE的上下文中可以看到。当声明不合格时(由于在同一命名空间中(,MSVC往往难以对具有限定条件的模板进行越界定义。我在处理SFINAE的形式时经常遇到这种情况,现在看来concepts也会出现这种情况。

例如,MSVC拒绝有效代码:

namespace nsp {
template <typename T>
using is_convertible_to_bool = std::is_convertible<T, bool>;
template <typename T, std::enable_if_t<is_convertible_to_bool<T>::value,int> = 0>
void example(const T& x);
} // namespace nsp
template <typename T, std::enable_if_t<nsp::is_convertible_to_bool<T>::value,int>>
void nsp::example(const T& x)
{
}

实时示例

但是,如果您在namespace nsp:的is_convertible_to_bool上添加资格,MSVC将接受相同的代码

template <typename T, std::enable_if_t<nsp::is_convertible_to_bool<T>::value,int> = 0>
//                                     ^~~~~ fixes it
void example(const T& x);

实时示例

类似地,如果您更改struct C的定义以包含完全限定的概念名称:,那么您的代码示例实际上是有效的

template<nsp::Addable T>
//       ^~~~~
//       Qualifying here fixes the failure in MSVC
struct C
{
C();
};

实时示例


我没有时间检查编译器正确的查找规则标准(如果没有其他答案,稍后会这样做(,但我的期望实际上是MSVC提供了不正确的行为。基本名称查找应该在两个定义中选择相同的类型,因此代码应该是格式良好的。

相关内容

  • 没有找到相关文章

最新更新