构造函数内指向模板成员函数的指针是否会强制实例化?

发布于 2024-11-02 10:52:38 字数 754 浏览 4 评论 0原文

考虑以下头文件:

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

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

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

Consider the following header file:

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

It seems that assigning a pointer to Foo::read<T> in the constructor of a class, of which variable is then declared, cause instantiation:

// 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;

Is this solution reliable / portable / standard-conformant? (It works at least with Intel and GNU compilers.)

If you wonder why not to simply use template Foo::read<int>(int&); see this question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤芳又自赏 2024-11-09 10:52:38

是的,您的解决方案是便携式的。这是一种不同的方式

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

现在,每当 Bar 被隐式实例化时,它都会隐式实例化 Foo::read。不需要创建任何对象。

Yes, your solution is portable. Here is a different way

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

Now whenever Bar<T> is implicitly instantiated, it will implicitly instanitate Foo::read<T>. No object needs to be created.

那支青花 2024-11-09 10:52:38

14.7.1 是它所在的位置。 /2 说:

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

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

还有/9:

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

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

14.7.1 is where it's at. /2 says:

Unless a function template
specialization has been explicitly
instantiated or explicitly
specialized, the function template
specialization is implicitly
instantiated when the specialization
is referenced in a context that
requires a function definition to
exist.

Just like calling a function, taking a member function pointer requires that the function is defined in the program (perhaps in another TU). I believe that's what "requires a function definition to exist" means, so this is what causes the instantiation.

There's also /9:

An implementation shall not implicitly
instantiate a function template, a
member template, a non-virtual member
function, a member class or a static
data member of a class template that
does not require instantiation.

So the fact that GCC and Intel instantiate it suggests that everyone else should, since that which is not required is forbidden. Assuming everyone conforms, of course.

泪之魂 2024-11-09 10:52:38

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

换句话说,如果您尝试这样的操作:

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

那么在您声明 X 之前,Foo::read() 将不会被实例化。

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

When objects for Bar<type> are declared with actual types then definitely, Yes; it will instantiate Foo::read<type>(). However, it will be limited only to that function (say Foo::write<type>() will not be instantiated).

In other way, if you try something like this:

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

Then Foo::read<int>() will not be instantiated until you declare X<int>.

Edit:
In above example, directly declaring Bar<int> b1; (int instead of T) inside X is also NOT sufficient. Its containing type X<> has to be instantiated with actual (i.e. non-template) type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文