为什么需要内联模板特化?
Why do templates specialisations need to be inlined?
我指的是这个答案:
我 运行 进入与引用问题的 OP 类似的问题,
有功能
template<typename T>
void func(T& val);
及其专业
template<>
void func<mytype>(mytype& val);
导致重复符号链接器错误(这些方法在我的 header 末尾包含的“.tpp”文件中实现)。
将 inline
添加到专用函数解决了这个问题。为什么?
这将在没有内联的情况下工作:
file1.h
template<typename T> void func(T& val);
template<> void func<mytype>(mytype& val);
file1.cpp
template<> void func<int>(int& ) {}
但是如果你在头文件中定义模板特化,那么你可能会违反ODR
好吧,如果你想要标准报价,那将在 [temp.expl.spec]/12
结束
An explicit specialization of a function or variable template is
inline only if it is declared with the inline specifier or defined as
deleted, and independently of whether its function or variable
template is inline. [ Example:
template<class T> void f(T) { /* ... */ }
template<class T> inline T g(T) { /* ... */ }
template<> inline void f<>(int) { /* ... */ } // OK: inline
template<> int g<>(int) { /* ... */ } // OK: not inline
— end example ]
这就是您必须这样做的原因。它是独立的,因为我认为不这样做会造成不必要的限制,正如 所证明的那样。
根据 c++ 标准中的条款 3.2:4
Every program shall contain exactly one definition of every non-inline
function or variable that is odr-used in that program; no diagnostic
required. The definition can appear explicitly in the program, it can
be found in the standard or a user-defined library, or (when
appropriate) it is implicitly defined (see 12.1, 12.4 and
12.8). An inline function shall be defined in every translation unit in which it is odr-used.
这解释了为什么在未声明内联专用函数时会出现 link 次错误。该程序将包含专门功能的多个定义,每个模块都有一个,包括 .tpp 文件,这打破了标准的条件。声明专用函数时 inline
将使该函数满足同一子句的第二部分,即必须在使用该函数的每个模块中定义一个内联函数。
当参数化函数不是专门的时,它包含在条款 3.2:6 中:
There can be more than one definition of a class type (Clause 9),
enumeration type (7.2), inline function with external linkage (7.1.2),
class template (Clause 14), non-static function template (14.5.6),
static data member of a class template (14.5.1.3), member function of
a class template (14.5.1.1), or template specialization for which some
template parameters are not specified (14.7, 14.5.5) in a program
provided that each definition appears in a different translation unit
该子句规定,只要代码中未指定至少一个模板参数,就可以对同一模板函数进行多次定义。这是为了允许仅根据本地信息决定是否应在模块中实例化参数化函数。
我指的是这个答案:
我 运行 进入与引用问题的 OP 类似的问题, 有功能
template<typename T>
void func(T& val);
及其专业
template<>
void func<mytype>(mytype& val);
导致重复符号链接器错误(这些方法在我的 header 末尾包含的“.tpp”文件中实现)。
将 inline
添加到专用函数解决了这个问题。为什么?
这将在没有内联的情况下工作:
file1.h
template<typename T> void func(T& val);
template<> void func<mytype>(mytype& val);
file1.cpp
template<> void func<int>(int& ) {}
但是如果你在头文件中定义模板特化,那么你可能会违反ODR
好吧,如果你想要标准报价,那将在 [temp.expl.spec]/12
结束An explicit specialization of a function or variable template is inline only if it is declared with the inline specifier or defined as deleted, and independently of whether its function or variable template is inline. [ Example:
template<class T> void f(T) { /* ... */ } template<class T> inline T g(T) { /* ... */ } template<> inline void f<>(int) { /* ... */ } // OK: inline template<> int g<>(int) { /* ... */ } // OK: not inline
— end example ]
这就是您必须这样做的原因。它是独立的,因为我认为不这样做会造成不必要的限制,正如
根据 c++ 标准中的条款 3.2:4
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is odr-used.
这解释了为什么在未声明内联专用函数时会出现 link 次错误。该程序将包含专门功能的多个定义,每个模块都有一个,包括 .tpp 文件,这打破了标准的条件。声明专用函数时 inline
将使该函数满足同一子句的第二部分,即必须在使用该函数的每个模块中定义一个内联函数。
当参数化函数不是专门的时,它包含在条款 3.2:6 中:
There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit
该子句规定,只要代码中未指定至少一个模板参数,就可以对同一模板函数进行多次定义。这是为了允许仅根据本地信息决定是否应在模块中实例化参数化函数。