2014-01-31 2 views
2

Использование N3651 в качестве основы,переменного шаблон в области видимости класса

A variable template at class scope is a static data member template.

Пример, приведенный в:

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 

Что дает?

+0

Это необходимо? Как популярный отказ от ответственности, «это ранний проект. Известно, что он неполный и интрект, и у него много плохого форматирования. «Я не уверен, что нам нужен один вопрос/ответ для каждой ошибки в предложениях и проектах. –

ответ

4

EDIT: committee has spoken, Clang верно, если требуется ключевое слово static для статических шаблонов элементов данных. Примеры, приведенные в 14/1, равны , а не. Надеемся, что следующий пересмотр рабочего проекта устранит двусмысленность из текста.


Это кажется быть ошибка в Clang, но формулировка в проекте стандарта неоднозначно. Я считаю, что намерение заключается в том, что ключевое слово static неявно. Если это не было намерение, предположительно стандартная формулировка была бы более похожей на строку «Шаблон переменной в классе scope должен быть шаблон статических данных». вместо «Шаблон переменной в классе scope : шаблон статических данных». ( 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 states in his comment, фактический нормативный текст раздела противоречит примеру. Они пишут Кланг в текст стандарта, поэтому пример диагностирован как плохо сформированный. The committee is aware that the wording for variable templates needs some help in various places, поэтому я уверен, что в следующем проекте/C++ 14 будет проведена очистка.

+2

Я не думаю, что это понятно.14/1 также говорит: «Декларация, введенная объявлением шаблона переменной, является переменным шаблоном». и 'T pi = T {3.14};' является объявлением нестатического элемента данных, а не переменной. Таким образом, либо нормативный текст является неправильным, либо примером. –

+0

@RichardSmith Я согласен с тем, что формулировка в лучшем случае двусмысленна и в худшем случае противоречива по местам. Я интерпретировал примеры как нормативные, так как формулировка обычно немного подозрительна для функций при первой интеграции. Я собирался следить за этим ответом и записывать отчет об ошибке после прочтения предложений шаблонов переменных для уточнения, но я был отвлечен. Я уточню ответ. – Casey

+3

После обсуждения основного рефлектора WG21 мы решили, что здесь должно быть указано ключевое слово 'static', и это неверный пример. –

0

Если попробовать первый пример, лязг кашляет волшебную ошибку сразу:

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

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

Смежные вопросы