显式专业化必须先于其首次使用
Explicit specialization must precede its first use
我需要能够将存根代码插入到模板函数中,其中存根代码是专用的。如果我使用
这样的蹦床,大多数编译器都允许这样做
template <class T>
T foo(T t) {
if(Stub<T>::enabled) {
return Stub<T>::stub(t);
}
/* actual code here */
}
/* use of foo occurs here */
template <>
int Stub<int>::stub(int) { /* stub code */ }
至少这适用于大多数版本的 GCC、clang 和 MSVC。有一些旧版本的 GCC 和 GCC 派生的编译器不接受这一点,并抱怨 Stub<T>::stub
的显式特化在首次使用后无法发生。
我的问题是——这些编译器是否有解决方法——如果没有,就标准而言,这是允许的吗?还是我只是 "do the right thing" 依赖 GCC/Clang/MSVC?
这是 ODR 问题。我认为不需要诊断,但代码格式不正确。
要解决此问题,您可以在定义专业化之前声明:
template <class T>
T foo(T t) {
if(Stub<T>::enabled) {
return Stub<T>::stub(t);
}
/* actual code here */
}
/* declaration */
template <>
int Stub<int>::stub(int);
/* use of foo occurs here */
template <>
int Stub<int>::stub(int) { /* stub code */ }
为什么我认为这是 ODR 问题。
看看example1 and example2。两者都以相同的方式使用模板。一个是内联主模板,另一个是调用缺失的专业化,因为专业化可能在某个地方的另一个翻译单元中。
将专业化添加到示例 1 中的另一个翻译单元将是 IFNDR,这真的很难调试。
在此使用函数foo
/* use of foo occurs here */
存在隐式实例化特化 Stub<int>::stub(int)
。
但是在实例化之后提供了特化的声明
template <>
int Stub<int>::stub(int) { /* stub code */ }
程序格式错误。然而,该标准不需要编译器诊断。
来自 C++ 17 标准(17.8.3 显式特化)
6 If a template, a member template or a member of a class template
is explicitly specialized then that specialization shall be declared
before the first use of that specialization that would cause an
implicit instantiation to take place, in every translation unit in
which such a use occurs; no diagnostic is required. If the program
does not provide a definition for an explicit specialization and
either the specialization is used in a way that would cause an
implicit instantiation to take place or the member is a virtual member
function, the program is ill-formed, no diagnostic required. An
implicit instantiation is never generated for an explicit
specialization that is declared but not defined.
您需要的是编写满足标准的代码。那就是将显式特化的声明放在隐式实例化之前。
我需要能够将存根代码插入到模板函数中,其中存根代码是专用的。如果我使用
这样的蹦床,大多数编译器都允许这样做template <class T>
T foo(T t) {
if(Stub<T>::enabled) {
return Stub<T>::stub(t);
}
/* actual code here */
}
/* use of foo occurs here */
template <>
int Stub<int>::stub(int) { /* stub code */ }
至少这适用于大多数版本的 GCC、clang 和 MSVC。有一些旧版本的 GCC 和 GCC 派生的编译器不接受这一点,并抱怨 Stub<T>::stub
的显式特化在首次使用后无法发生。
我的问题是——这些编译器是否有解决方法——如果没有,就标准而言,这是允许的吗?还是我只是 "do the right thing" 依赖 GCC/Clang/MSVC?
这是 ODR 问题。我认为不需要诊断,但代码格式不正确。
要解决此问题,您可以在定义专业化之前声明:
template <class T>
T foo(T t) {
if(Stub<T>::enabled) {
return Stub<T>::stub(t);
}
/* actual code here */
}
/* declaration */
template <>
int Stub<int>::stub(int);
/* use of foo occurs here */
template <>
int Stub<int>::stub(int) { /* stub code */ }
为什么我认为这是 ODR 问题。
看看example1 and example2。两者都以相同的方式使用模板。一个是内联主模板,另一个是调用缺失的专业化,因为专业化可能在某个地方的另一个翻译单元中。
将专业化添加到示例 1 中的另一个翻译单元将是 IFNDR,这真的很难调试。
在此使用函数foo
/* use of foo occurs here */
存在隐式实例化特化 Stub<int>::stub(int)
。
但是在实例化之后提供了特化的声明
template <>
int Stub<int>::stub(int) { /* stub code */ }
程序格式错误。然而,该标准不需要编译器诊断。
来自 C++ 17 标准(17.8.3 显式特化)
6 If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required. An implicit instantiation is never generated for an explicit specialization that is declared but not defined.
您需要的是编写满足标准的代码。那就是将显式特化的声明放在隐式实例化之前。