Шаблон переменной в области видимости класса

Используя N3651 в качестве основы,

Шаблон переменной в области видимости - это шаблон статического члена данных.

Пример приведен ниже:

struct matrix_constants {  
 template <typename T>   
  using pauli = hermitian_matrix<T, 2>;

Все же все следующие определения дают ошибку:

struct foo
{
    template <typename T>
    T pi = T{3.14};
};

template <typename T>
struct foo2
{
    template <typename U = T>
    U pi = U{3.14};
};

template <typename T>
struct foo3
{
    template <T>
    T pi = 42;
};

error: member 'pi' declared as a template

Что дает?

2 ответа

Решение

РЕДАКТИРОВАТЬ: Комитет говорил, Clang правильно требовать static ключевое слово для шаблонов статических данных. Примеры, приведенные в 14/1, не верны. Надеемся, что следующий пересмотр рабочего проекта устранит двусмысленность из текста.


Этопохоже на ошибку в Clang, но формулировка в проекте стандарта неоднозначна. Я считаю, что намерение состоит в том, что ключевое слово staticнеявно. Если бы это не было целью, предположительно стандартная формулировка была бы более похожа на строку "Шаблон переменной в области видимостидолжен быть шаблоном статического члена данных". вместо "Шаблон переменной в области видимости- это шаблон статического члена данных". ( N3797 §14 / 1) (по общему признанию ненормативный) пример, приведенный в §14/1, объявляет три шаблона переменных члена класса, ни один из которых не имеетstaticключевое слово:

struct matrix_constants {
  template<class T>
   using pauli = hermitian_matrix<T, 2>;
  template<class T>
   constexpr pauli<T> sigma1 = { { 0, 1 }, { 1, 0 } };
  template<class T>
   constexpr pauli<T> sigma2 = { { 0, -1i }, { 1i, 0 } };
  template<class T>
   constexpr pauli<T> sigma3 = { { 1, 0 }, { -1, 0 } };
};

Пример в 14.5.1.3 Статические данные-члены шаблонов классов [temp.static]/1 особенно использует static:

struct limits {
  template<class T>
    static const T min; // declaration
};

template<class T>
  const T limits::min = { }; // definition

так что, по крайней мере, это не запрещено.

Как пишет @RichardSmith в своем комментарии, фактический нормативный текст раздела противоречит этому примеру. Они пишут Clang к тексту стандарта, поэтому пример диагностируется как плохо сформированный. Комитет осознает, что формулировка переменных шаблонов нуждается в некоторой помощи в разных местах, поэтому я уверен, что в следующем проекте / C++14 будет некоторая очистка.

Если вы попробуете первый пример, clang сразу же покажет магическую ошибку:

template <typename T, size_t N>
struct hermitian_matrix { };

struct foo
{
    template <typename T>
    using pauli = hermitian_matrix<T, 2>;

    template <typename T>
    constexpr pauli<T> sigma1 = { { 0, 1 }, { 1, 0 } };
};

error: non-static data member cannot be constexpr; did you intend to make it static?

Очевидно в области видимости, переменные шаблоны должны быть объявлены как статические. clang не исправляет правильную ошибку, если вы не объявите ее как constexpr, что может ввести в заблуждение. А также, их пример статического члена данных:

struct foo
{
    template <typename T>
    static T bar;
};

template <typename T>
T foo::bar = T{3.14};

может сбить вас с толку, потому что можно подумать, что весь смысл шаблонов переменных элементов заключается в замене статических элементов данных.

Другие вопросы по тегам