C++ Clang和GCC在转换C++;17

C++ Clang和GCC在转换C++;17,c++,g++,language-lawyer,clang++,c++17,C++,G++,Language Lawyer,Clang++,C++17,我基本上有一个依赖于非类型模板参数的类。我定义了一个强制转换,以便非类型模板参数N的对象可以转换为M的另一个对象。我有一个可以重现这种情况的最小示例: template<auto Integral> class Test{ public: typedef decltype(Integral) value_type; static constexpr value_type N = Integral; constexpr Test

我基本上有一个依赖于非类型模板参数的类。我定义了一个强制转换,以便非类型模板参数
N
的对象可以转换为
M
的另一个对象。我有一个可以重现这种情况的最小示例:

template<auto Integral>
class Test{
    public:
        typedef decltype(Integral) value_type;
        static constexpr value_type N = Integral;

        constexpr Test (const value_type& x = 0);

        template<auto Integral2>
        constexpr explicit operator Test<Integral2>() const;
    private:
        value_type n;
};

template<auto Integral>
constexpr Test<Integral>::Test (const value_type& x){
    if (x < 0){
        n = N - (-x)%N;
    }
    else{
        n = x%N;
    }
}

template<auto Integral> template<auto Integral2>
constexpr Test<Integral>::operator Test<Integral2>() const{
    return Test<Integral2>(n%(Test<Integral2>::N));
}
这让我觉得clang++并没有找到一个“正确”的转换声明,但我不知道

注意:第一个错误仅在声明与定义分离时出现。否则,它似乎是正确的

这是clang++产生的第二个错误:

error: a non-type template parameter cannot have type 'auto'
但是这个错误让我更加惊讶,因为这个错误告诉我一些在C++17中应该是有效的东西。也许我遗漏了什么,因为这对我来说毫无意义

请记住,第二个错误仅在转换时出现。实际代码中的任何地方都会出现错误(即使还有更多的
auto
非类型模板参数)

在这一点上,我有一些问题:

  • 在clang编译器的情况下,是什么产生了错误
  • 根据标准,哪一个是正确的

    • 这是一个叮当作响的错误。这是一个简短的复制品:

      template <int A>
      struct X {
          template <auto B>
          X<B> foo();
      };
      
      template <int A>
      template <auto B>
      X<B> X<A>::foo() {
          return {};
      }
      
      template<typename>
      struct S {
          template<auto n>
          static void f() {
              +n;
          }
      };
      
      它失败于:

      source.cpp:5:3: error: invalid argument type 'auto' to unary expression
                      +n;
      

      我看不出这个越界的定义有什么错。这似乎是一个叮当作响的错误。@cdhowie如果是这样的话,我应该报告它吗?可能吧,但我会等待更好的答案。我的评论是基于我对语言理解的推测;语言律师可能会在接下来的几个小时内给你一个明确的答案。@1201程序我不想过早下结论,因为我不是专家。我们不能仅仅假设这是GCC的错误。我发现在第二个示例中将
      +n
      更改为
      +(decltype(n))(n)
      以某种方式修复了它。。。
      source.cpp:5:3: error: invalid argument type 'auto' to unary expression
                      +n;