Например:
class example{
public:
template <class T> static constexpr T var = T(1.5);
};
int main(){
int a = example::var<int>;
example obj;
int b = obj.var<int>;
return 0;
}
GCC создает ошибку для обоих:
'example::var<T>' is not a function template
и 'var' is not a member template function
Clang правильно компилирует первый, но создает ошибку для второго: cannot refer to member 'var' in 'example' with '.'
В соответствии со стандартом С++ 14 (ISO/IEC 14882: 2014):
Раздел 14, пункт 1.
Шаблон переменной в области класса представляет собой шаблон статических данных.
Раздел 9.4, абзац 2.
Статический член s класса X может ссылаться на использование выражения с квалифицированным идентификатором X:: s; нет необходимости использовать синтаксис доступа к члену класса (5.2.5) для ссылки на статический член. Статический член может ссылаться на использование синтаксиса доступа к члену класса, и в этом случае оценивается выражение объекта.
Следовательно, IMHO, переменная шаблон в классе (например, шаблон участника статических данных) может упоминаться в обоих направлениях. Может ли это быть ошибкой в компиляторах?
Единственное, что я нашел, чтобы попытаться оправдать такое поведение, - это предложение в разделе 9.4.2, абзац 1:
Статический член данных не является частью подобъектов класса.
Однако оба вышеупомянутых параграфа остаются в силе. Кроме того, я попробовал тот же пример, ссылаясь на другие статические элементы, такие как переменная, функция и шаблон функции, и все они успешно компилируются как в GCC, так и в Clang.
class example{
public:
static int constexpr variable = 1;
void static function(){ return; }
template <class T> void static function_template(){ return; }
};
int main(){
example obj;
int a = obj.variable;
int b = example::variable;
obj.function();
example::function();
obj.function_template<int>();
example::function_template<int>();
return 0;
}
Спасибо в Advance.
Примечание 1: версии компилятора - clang 3.7.0 и gcc 5.2.1.
Примечание 2: требуется ключевое слово static
: Переменный шаблон в области класса
Примечание 3: поскольку я хочу инициализировать шаблон переменной, требуется также ключевое слово constexpr
, потому что в моем фактическом коде я создам его с помощью float, double и long double (см. С++ 14 Standard (ISO/IEC 14882: 2014), раздел 9.4.2, пункт 3).
Примечание 4: фактические "определения" этих статических элементов данных вне класса (т.е. template <class T> constexpr T example::var;
) не нужны в этих примерах. Я тоже пытался, но это не имеет значения.