C ++ 20概念:MSVC的行外定义失败,但在GCC或clang中不行 [英] C++20 Concepts: out-of-line-definition fails with MSVC but not in GCC or clang

查看:110
本文介绍了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(x8619.28)拒绝,并显示错误消息:

As shown here GCC (10.2) and clang (11.0) accept the code while MSVC (x86 19.28) rejects it with the error message:

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

这是MSVC错误还是GCC和clang错误地接受了它?或者,我是否有些愚蠢?如果我将离线定义移动到名称空间 nsp 中,它似乎也适用于MSVC.参见此示例.

Is this a MSVC bug or are GCC and clang wrong accepting it? Or alternatively, did I something stupid? If I move the out-of-line definition into the namespace nsp it seems to work for MSVC, as well. See this example.

推荐答案

此行为是MSVC中的一个可观察到的偏差,通常在模板和SFINAE的上下文中可以看到.当声明不合格时(由于位于同一个命名空间中),MSVC往往很难对具有限定条件的模板进行脱机定义.在处理SFINAE形式时,我经常遇到这种情况,而且看来现在也必须在 concept s中发生这种情况.

This behavior is an observable deviation in MSVC that has been seen usually in the context of templates and SFINAE. MSVC tends to have difficulty with out-of-line definitions of templates that have qualifications when the declarations are not qualified (from being in the same namespace). I've often encountered this when dealing with forms of SFINAE, and it appears this must be also occurring with concepts now too.

例如,MSVC拒绝有效的代码:

For example, MSVC rejects the valid code:

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将接受相同的代码:

However, MSVC will accept the same code, provided you add qualifications on the is_convertible_to_bool from 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 的定义以包含完全限定的概念名称,则您的代码示例实际上可以工作:

Similarly, your code sample actually works if you change the definition of struct C to include the fully qualified concept name:

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

在线示例

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

I don't have time to check the standard for lookup rules for which compiler is correct (will do this later if no other answer appears), but my expectation is actually that MSVC is providing incorrect behavior. The basic name lookup should select the same type in both definitions, and thus the code should be well-formed.

这篇关于C ++ 20概念:MSVC的行外定义失败,但在GCC或clang中不行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆