在构造函数中指向模板成员函数的指针会强制实例化吗?

Will the pointer to a template member function inside a constructor force instantiation?

本文关键字:指针 实例化 函数 构造函数 成员      更新时间:2023-10-16

考虑以下头文件:

// 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&);,请看这个问题

是的,您的解决方案是可移植的。这里有一个不同的方法

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>。不需要创建对象。

14.7.1是它的位置。/2说:

除非是函数模板专业化已经被明确地实例化或显式地专门化,即函数模板专门化是隐含的在专门化时实例化引用的上下文是需要一个函数定义来存在。

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

还有/9:

实现不能隐式地实例化一个函数模板成员模板,非虚成员函数、成员类或静态类模板的数据成员不需要实例化。

因此GCC和Intel实例化它的事实表明其他人都应该这样做,因为不需要的是被禁止的。当然,前提是每个人都遵守。

用实际类型声明Bar<type>的对象时,那么肯定地,Yes;它将实例化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>

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

相关文章: