C++20 Concepts: out-of-line-definition fails with MSVC but not in GCC or clang

好久不见. 提交于 2021-01-27 19:54:51

问题


Consider this little code snippet

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() {};

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. 

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.


回答1:


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.

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)
{

}

Live Example

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);

Live example

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();
    };

Live Example


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.



来源:https://stackoverflow.com/questions/65702336/c20-concepts-out-of-line-definition-fails-with-msvc-but-not-in-gcc-or-clang

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!