所有模板实例的 C++ 单一函数指针

C++ Single function pointer for all template instances

是否有一种不使用宏而指向模板函数的所有实例的简洁方法?

我有几个模板化函数,我想测试各种类型:

template<typename T>
void function1() {
  return;
}

template<typename T>
void function2() {
  return;
}

template<typename T>
void function3() {
  return;
}

我可以用宏来做到这一点:

#define TEST_ACROSS_TYPES(fn) \
fn<int>();  \
fn<bool>(); \
fn<char>(); \
fn<double>(); \

TEST_ACROSS_TYPES(function1);
TEST_ACROSS_TYPES(function2);

但是,(1) 宏很丑陋并且其他人难以遵循,并且 (2) 我正在使用 CATCH,这在使用宏设置测试用例时效果不佳。

有没有办法做这样的事情:

void testAcrossTypes(SomeType f) {
  f<int> ();
  f<bool> ();
  f<char> ();
  f<double> ();
}

除了定义 SomeType 的问题外,这看起来更清晰了。这个问题(How to define typedef of function pointer which has template arguments)解释了如何定义一个指向模板函数的指针;但是,需要指定模板参数。


澄清一下:假设 function1function2function3 分别测试不同的模板函数。每个函数都需要针对 intbytechardouble 等进行测试。我想避免必须显式设置许多(即 num_functions * num_types) 测试每个函数。相反,我想要一个指向测试函数(function1function2 等)并为每个模板类型运行它的方法,从而合并

function1<int>();
function1<byte>();
function1<char>();
function1<double();
...
function2<int>();
function2<byte>();
function2<char>();
function2<double();
...
function3<int>();
function3<byte>();
function3<char>();
function3<double();
...

每个测试函数只调用一次

testAcrossTypes(function1);
testAcrossTypes(function2);
testAcrossTypes(function3);

你想用

完成什么
void testAcrossTypes(SomeType f) {
  f<int> ();
  f<bool> ();
  f<char> ();
  f<double> ();
}
如果 SomeType 可以是模板模板参数,则

是可能的。但是,标准不允许函数模板作为模板模板参数。

来自 C++11 标准:

14.3.3 Template template arguments

1 A template-argument for a template template-parameter shall be the name of a class template or an alias template, expressed as id-expression.

你最好的选择是使用仿函数而不是函数。示例:

template<typename T>
struct function1
{
   void operator()() {
      return;
   }
};

template<typename T>
struct function2
{
   void operator()() {
      return;
   }
};

template < template <typename> class F>
void testAcrossTypes() {
  F<int>()();
  F<bool>()();
  F<char>()();
  F<double>()();
}

int main()
{
   testAcrossTypes<function1>();
   testAcrossTypes<function2>();
}

您可以通过类型擦除仿函数来完成它,如下例中的仿函数:

#include<vector>

template<typename T>
void function1() { }

template<typename T>
void function2() { }

template<typename T>
void function3() { }

struct Test {
    template<typename T>
    static void proto() {
        function1<T>();
        function2<T>();
        function3<T>();
    }

    void operator()() {
        for(auto &f: vec) f();
    }

    template<typename... T>
    static Test create() {
        Test test;
        int arr[] = { (test.vec.emplace_back(&proto<T>), 0)... };
        (void)arr;
        return test;
    }

    using func = void(*)(void);
    std::vector<func> vec;
};

void testAcrossTypes(Test test) {
    test();
}

int main() {
    testAcrossTypes(Test::create<int, bool, char, double>());
}

两种情况修改起来都很容易:

  • 需要在proto静态成员方法中添加新函数,仅此而已

  • 添加一个新的类型就是在调用create时使用它的问题,如上例

函子将负责创建要执行的 N*M 个调用。
此外,您无需将函数移动到一堆结构中即可使用它们。