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

C++ C++;20个概念:越界定义在MSVC中失败,但在GCC或clang中失败,c++,c++20,c++-concepts,C++,C++20,C++ Concepts,考虑一下这个小代码片段 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();

考虑一下这个小代码片段

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() {};
名称空间nsp
{
模板
概念可添加=需要(常数T&a、常数T&b)
{
{a+b}->std::可转换为;
};
模板GCC(10.2)和clang(11.0)接受该代码,而MSVC(x86 19.28)拒绝该代码,并显示错误消息:

error C3855: 'nsp::C<T>': template parameter 'T' is incompatible with the declaration. 
错误C3855:“nsp::C”:模板参数“T”与声明不兼容。

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

此行为是MSVC中的一个明显偏差,通常在模板和SFINAE.MS的上下文中可以看到VC往往很难在声明不合格(来自同一名称空间)的情况下对具有限定条件的模板进行越界定义。我在处理SFINAE的形式时经常遇到这种情况,现在看来
concept
s也一定会出现这种情况

例如,MSVC拒绝有效代码:

名称空间nsp{
模板
使用is_convertive_to_bool=std::is_convertive;
模板
无效示例(常数T&x);
}//名称空间nsp
模板
无效nsp::示例(常量T&x)
{
}

但是,MSVC将接受相同的代码,前提是您在
名称空间nsp
中的
可转换为\u bool

模板
//^~~~~解决了它
无效示例(常数T&x);

类似地,如果将
struct C
的定义更改为包含完全限定的概念名称,那么代码示例实际上也可以工作:

模板
//       ^~~~~
//在此处进行限定可修复MSVC中的故障
结构C
{
C();
};



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

我似乎无法在该名称下找到此特定语言功能,但您知道吗?@yvbaker它被称为“概念”,并且根据链接页面,MSVC只提供部分支持。。有一些功能在MSVC中工作,但在GCC中不起作用。MSVC更新的频率低于GCC。另一方面,GCC的一个常见问题是编译器在您脚下的更改频率。@Yksisarvinen啊,太好了!我今天也学到了一些新东西then@Hack20c++20标准h最后,我们应该开始学习和适应它。我根本不认为这是一个“匆忙”。