2

考虑以下头文件:

// Foo.h
class Foo {
    public: template <typename T> void read(T& value);
};

似乎Foo::read<T>在类的构造函数中分配一个指针,然后声明其中的变量,会导致实例化:

// Foo.cc
#include "Foo.h"

template <typename T>
void Foo::read(T& value) { /* do something */ }

template <typename T> struct Bar {
    Bar<T>() { void (Foo::*funPtr)(T&) = &Foo::read<T>; }
};

static Bar<int  > bar1;
static Bar<long > bar2;
static Bar<float> bar3;

该解决方案是否可靠/便携/符合标准?(它至少适用于 Intel 和 GNU 编译器。)

如果您想知道为什么不简单地使用,template Foo::read<int>(int&);请参阅此问题

4

3 回答 3

2

14.7.1 就是它所在的地方。/2 说:

除非函数模板特化已被显式实例化或显式特化,否则当在需要函数定义存在的上下文中引用特化时,函数模板特化将被隐式实例化。

就像调用函数一样,获取成员函数指针需要在程序中定义函数(可能在另一个 TU 中)。我相信这就是“需要一个函数定义存在”的意思,所以这就是导致实例化的原因。

还有 /9:

实现不应隐式实例化不需要实例化的类模板的函数模板、成员模板、非虚拟成员函数、成员类或静态数据成员。

所以 GCC 和 Intel 实例化它的事实表明其他人都应该这样做,因为不需要的东西是被禁止的。当然,假设每个人都符合要求。

于 2011-04-20T10:31:41.207 回答
2

是的,您的解决方案是可移植的。这是另一种方式

template <typename T, T> struct user { };
template <typename T> struct Bar {
    typedef user< void (Foo::*)(T&), &Foo::read<T> > user_type;
};

现在,无论何时Bar<T>隐式实例化,它都会隐式实例化Foo::read<T>。不需要创建对象。

于 2011-04-20T16:36:43.890 回答
1

当用实际类型Bar<type>声明对象时,肯定是,是的;它会实例化Foo::read<type>()。但是,它将仅限于该功能(例如Foo::write<type>()不会被实例化)。

换句话说,如果你尝试这样的事情:

template<typename T>
struct X
{
  Bar<T> b1;  // this is required but not sufficient to instantiate Foo::read<T>()
};

然后Foo::read<int>()在你声明之前不会被实例化X<int>

编辑:在上面的例子中,直接在里面声明Bar<int> b1;int而不是) 也是不够的。它的包含类型必须用实际(即非模板)类型实例化。TXX<>

于 2011-04-20T10:20:18.053 回答