实例化多种类型的成员函数模板

Instantiate member function templates for multiple types

本文关键字:成员 函数模板 类型 种类 实例化      更新时间:2023-10-16

我有几个类,其中包含模板化的成员函数和预定义的类型列表,它们将与之一起使用(Wandbox链接:

// main.cpp:
#include "class.h"
int main(int argc, char** argv) {
A a;
a.foo(5);
a.foo(5.);
B b;
//b.bar(1,2,3,4); b.bar(1,2,3.,4);
return 0;
}
// class.h
#pragma once
struct A {
template<typename T> void foo(T x);
};
struct B {
template<typename T> void bar(int p1, int p2, T x, int p3);
};

// class.cpp
#include <iostream>
#include "class.h"
template<typename T> void A::foo(T x) {
std::cout << x << std::endl;
}
// explicit, but very verbose
// template void A::foo(int);
// ...
template<typename T> void ignore(T fn) {/* Use fn? */}
template<class Class>
void instantiate(Class) {
// List all types the function should be instantiated for here
ignore(&Class::template foo<int>);
ignore(&Class::template foo<double>);
}
// works, instantiates A::foo<int> and A::foo<double>
template void instantiate(A);
// How to pass B::foo and additional parameters?
// template void instantiate(B);

键入要用实例化的成员函数和类型的每个组合,但它有几个缺点:

  • 这很乏味
  • 必须键入带有每个参数的整个函数签名,并且
  • 必须在多个位置更改函数签名
  • 必须为每个成员函数向列表中添加一个类型

我上述解决方法适用于我测试过的大多数旧编译器(C++03 兼容性将是一个巨大的优势(,但我不确定是否允许智能编译器删除未使用的参数和函数实例化。

对于常规函数,有一些解决方法,但据我了解,它们不适用于成员函数。

如何将我的instantiate函数更改为也接受成员函数和其他参数?

经过多次尝试和错误,我发现了即使启用了优化也可以工作的东西(Wandbox(:


// main.cpp as above
// class.h
#pragma once
// Create instantiations for templated functions by keeping their addresses
// and therefore forcing the compiler to keep their object code
// attribute((unused)) silences the clang/gcc warning
template <typename T> void ignore(T t) {static __attribute__((used)) T x = t;}
struct A {
template<typename T> void foo(T x);
template<typename T> friend void instantiate(T); // let instantiate call the helper function in case it's private
// helper function that instantiates all member functions
template<typename T> void helper() { ignore(&A::foo<T>); }
};
struct B {
template<typename T> void bar(int p1, int p2, T x, int p3);
// same procedure as above
template<typename T> friend void instantiate(T);
template<typename T> void helper() { ignore(&B::bar<T>); }
};

// class.cpp
#include 
#include "class.h"
template void A::foo(T x) {
std::cout  void B::bar(int, int, T, int) {}
template
void instantiate(Class) {
// List all types the function should be instantiated for here
ignore(&Class::template helper);
ignore(&Class::template helper);
}
template void instantiate(A);
template void instantiate(B);

为了避免更复杂的模板魔术,我添加了一个模板函数(template<typename T> void helper()(,该函数由instantiate函数实例化,其中列出了要实例化的函数的所有所需类型。

之后,template void instantiate(A)将实例化A::helper中列出的所有成员函数。