考虑一下这个小代码片段
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形式时,我经常遇到此问题,而且现在看来concept
s也必须发生这种情况。
例如,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)
{
}
但是,MSVC将接受相同的代码,只要你上添加资格is_convertible_to_bool
的namespace nsp
:
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提供了错误的行为。基本名称查找应在两个定义中选择相同的类型,因此代码应格式正确。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句