为什么一些看起来像普通类型定义的表达式意外地变成了模板声明?
Why some expression that looks like a definition for normal types unexpectedly turns out to be a declaration for templates?
这些表达式都是普通类型的定义:
int num;
bool flag;
但是一些看起来像普通类型定义的表达式意外地变成了模板的声明(详情见下文和https://ibb.co/k0qCHp2)!
这里是相关的代码片段(https://godbolt.org/z/a9W9Wc):
#include<iostream>
template<typename T>
class Test
{
public:
static constexpr int sdm = T(nullptr);
static int f(void){static_assert(sizeof(T)==0);}
int g(void){static_assert(sizeof(T)==0);}
};
int main()
{
Test<int> intTest; //**O'DWYER says that it's a declaration instead of a definition in his talk(see https://ibb.co/k0qCHp2)! Why?**
//But I can get this object's address indeed.
std::cout << &intTest << std::endl;
}
如果Test<int> intTest;
是声明,我可以得出结论std::vector<int> vec;
和std::map<std::string, int> map
也是声明。我说得对吗?
Test<int> intTest;
是变量intTest
的定义(也是声明,所有定义也是声明)。但是,这个事实与您隐含的“为什么这条线编译”的问题无关。它编译的原因是:它导致 class 模板特化 Test<int>
的隐式实例化,但 不是 其成员函数和静态数据成员。
[temp.inst]/2 The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or noexcept-specifiers of the class member functions, member classes, scoped member enumerations, static data members, member templates, and friends...
[temp.inst]/9 An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement (9.4.1), unless such instantiation is required...
那些成员函数和静态数据成员在使用时会被隐式实例化;正是在这一点上,编译器会发现他们的定义是错误的,并发出适当的诊断。
[temp.inst]/3 Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
这些表达式都是普通类型的定义:
int num;
bool flag;
但是一些看起来像普通类型定义的表达式意外地变成了模板的声明(详情见下文和https://ibb.co/k0qCHp2)!
这里是相关的代码片段(https://godbolt.org/z/a9W9Wc):
#include<iostream>
template<typename T>
class Test
{
public:
static constexpr int sdm = T(nullptr);
static int f(void){static_assert(sizeof(T)==0);}
int g(void){static_assert(sizeof(T)==0);}
};
int main()
{
Test<int> intTest; //**O'DWYER says that it's a declaration instead of a definition in his talk(see https://ibb.co/k0qCHp2)! Why?**
//But I can get this object's address indeed.
std::cout << &intTest << std::endl;
}
如果Test<int> intTest;
是声明,我可以得出结论std::vector<int> vec;
和std::map<std::string, int> map
也是声明。我说得对吗?
Test<int> intTest;
是变量intTest
的定义(也是声明,所有定义也是声明)。但是,这个事实与您隐含的“为什么这条线编译”的问题无关。它编译的原因是:它导致 class 模板特化 Test<int>
的隐式实例化,但 不是 其成员函数和静态数据成员。
[temp.inst]/2 The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or noexcept-specifiers of the class member functions, member classes, scoped member enumerations, static data members, member templates, and friends...
[temp.inst]/9 An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement (9.4.1), unless such instantiation is required...
那些成员函数和静态数据成员在使用时会被隐式实例化;正是在这一点上,编译器会发现他们的定义是错误的,并发出适当的诊断。
[temp.inst]/3 Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.