Шаблон переменной в области видимости класса
Используя 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};
может сбить вас с толку, потому что можно подумать, что весь смысл шаблонов переменных элементов заключается в замене статических элементов данных.