首页 > 解决方案 > 实例化多种类型的成员函数模板

问题描述

我有几个带有模板化成员函数的类和一个预定义的类型列表,它们将与它们一起使用(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函数以接受成员函数和附加参数?

标签: c++templatesinstantiationc++03explicit-instantiation

解决方案


After much trying and erroring I found something that works even with optimizations enabled (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);

To avoid more complicated template magic, I added a single template function (template<typename T> void helper()) that gets instantiated by the instantiate function where all desired types for the functions to be instantiated with are listed.

Afterwards, template void instantiate(A) will instantiate all member functions listed in A::helper.


推荐阅读