tipos template plantillas funciones c++ g++ language-lawyer clang++ c++17

template - plantillas c++



Clang y GCC no están de acuerdo en el especificador automático para el parámetro de plantilla que no es de tipo en un C++ de lanzamiento 17 (1)

Este es un error clang Aquí hay una breve reproducción:

template <int A> struct X { template <auto B> X<B> foo(); }; template <int A> template <auto B> X<B> X<A>::foo() { return {}; }

Si auto B es reemplazado por int B , Clang lo acepta. gcc lo acepta como está. Para clang, esto es solo un problema con las declaraciones de template anidadas. No hay nada sobre el auto como un parámetro de no tipo de marcador de posición que impida que se use para definir algo fuera de línea.

Mientras presentaba un nuevo error de clang, encontré 35655 , con una reproducción aún más corta:

template<typename> struct S { template<auto n> static void f() { +n; } };

que falla con:

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

Básicamente tengo una clase que depende de un parámetro de plantilla que no es de tipo. Definí una conversión para que un objeto de un parámetro de plantilla no tipo N pueda convertir a otro de M Tengo un ejemplo mínimo que puede reproducir la situación:

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

Estoy compilando usando GCC 7.2.0 y Clang 5.0.0 en Ubuntu 16.04 LTS con las banderas -O2 -std=c++17 .

El problema es que estaba compilando todo el tiempo usando g ++ y todo funcionó como se esperaba, pero luego probé clang ++ para verificar si todo estaba aún compilando bien.

Para mi sorpresa, ese no fue el caso, ya que clang ++ se quejó de algunas partes que g ++ no hizo. Puede comprobar una vista de diferencias en el Explorador del compilador .

Uno de los mensajes de error que produce clang ++ es:

error: out-of-line definition of ''operator Test<Integral2>'' does not match any declaration in ''Test<Integral>''

Esto me hace pensar que clang ++ no encontró una declaración "correcta" de la conversión, pero no lo sé.

Nota : Este primer error solo aparece al separar la declaración de la definición. De lo contrario, parece ser correcto.

Este es el segundo error que produce clang ++:

error: a non-type template parameter cannot have type ''auto''

Pero este me sorprende aún más porque el error dice algo que se supone que es válido en C ++ 17. Probablemente me esté perdiendo algo aquí porque esto simplemente no tiene sentido para mí.

Tenga en cuenta que este segundo error solo aparece en el caso de esta conversión. En cualquier parte del código real aparece el error (aunque hay muchos más parámetros de plantilla de tipo no auto ).

En este punto, tengo algunas preguntas:

  • ¿Qué está produciendo el error en el caso del compilador clang?
  • ¿Cuál es el correcto, según la norma?