Я играл с параметры автоматического шаблона и был удивлен, что этот код не компилировался:
constexpr auto bar = 2;
template<auto& T>
struct Foo {
auto operator()() const { return T; }
};
int main() {
Foo<bar> b;
b();
}
Visual Studio 15.7 (предварительная версия 4) выдает следующие ошибки:
error C2970: 'Foo': template parameter 'T': 'bar': an expression involving objects with internal linkage cannot be used as a non-type argument note: see declaration of 'Foo' note: see declaration of 'bar' error C2440: 'specialization': cannot convert from 'int' to 'int &' note: see reference to class template instantiation 'Foo<0>' being compiled error C2973: 'Foo': invalid template argument 'int' note: see declaration of 'Foo'
Потом после добавления inline
ошибка исчезла!
constexpr inline auto bar = 2;
Я думал, что переменные constexpr
неявно были inline
. Кроме того, как это повлияет на привязку моей переменной bar
?
Ах, спасибо за объяснение.
для неявно определенного конструктора копирования / перемещения это constexpr и inline. но не для примитивных типов.
Are all constexpr variable implicitly inline?
Нет. Неявно встроены только функции constexpr и статические элементы данных constexpr ([dcl.constexpr] / 1).
Also, how does that affect the linkage of my variable bar?
Переменная constexpr - const
([dcl.constexpr] / 9). Не встроенная переменная const
, которая явно не объявлена как extern
, имеет внутреннюю связь ([basic.link] / 3).
Ах! Вот где я запутался, неявная встроенная строка предназначена только для статических элементов данных constexpr, а не для всех переменных constexpr.
@GuillaumeRacicot, вы имеете право запутаться, исходная стандартная бумага сама по себе неверна, поскольку в ней не упоминается это различие. open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0386r0.pdf
@miradulo да, конечно ... Но GCC и Clang теперь также допускают ссылку или указатель на объект любой связи в качестве параметра шаблона, не являющегося типом. Таким образом, либо переменная constexpr действительно должна быть встроенной, и это ошибка визуальной студии, либо GCC и Clang принимают переменную, но все они имеют внутреннюю связь.