【发布时间】:2011-05-03 20:32:55
【问题描述】:
注意:the following code is illegal, but a conforming compiler is not required to reject it(有些没有)。
在我正在使用的库中,我有一个Foo 的模板函数声明和一个foobar.h 中Bar 的模板函数定义:
template<class C> int Foo();
template<class C> int Bar() {
return Something( Foo<C>() );
}
意图是其他代码可以像这样使用它:
#include "foobar.h"
int main() {
Bar<MyClass>();
return 0;
}
// Ideally, the usage (above) and the definition (below)
// would/could be in different translation units.
template<> int Foo<MyClass>() { return 5; }
问题: 有没有办法让这项工作也合法?
问题是(如果我理解正确的话)尽管编译,这在技术上是非法的:它违反了ODR,因为显式专业化和Bar<MyClass> 的使用都算作定义,尽管事实上在用例中没有可以使用的主体。
我想使用这种模式来参数化Foo 的原因是,作为我必须遵循的样式指南的结果,这是确保在Bar 的定义之前在词法上包含任何内容的唯一方法是为了将其包含在foobar.h 中。但是(出于我希望我不需要解释的原因)这是行不通的。
【问题讨论】:
-
Foo的最后一个定义应该是什么意思?绝对不清楚您要做什么。提供更多详细信息。 -
为什么不提供
int(*)(void)函数指针作为Bar的模板参数,而不是C 类?template <int(*FOO)()> int Bar() { return Something(FOO()); }。然后用户可以指示直接调用什么函数,而不是通过将Foo特化为MyClass来间接调用。然后如果愿意,可以用仿函数类替换函数指针。 -
我认为通常应该将免费函数模板声明为
inline以规避 ODR。 -
不确定 ODR,但代码似乎违反了 14.7.3/6:“如果模板 ... 是显式特化的,则应在第一次使用该特化之前声明该特化导致发生隐式实例化..."
-
一个想法:在 Bar 的定义之前没有要包含的特化,在第一次使用 Bar
之前就足够了,因为实例化点就在那里。 IE。我相信在 main()之前声明(甚至没有定义)专业化是合法的。也不是一个选择?
标签: c++ templates language-specifications one-definition-rule