2016-07-21 30 views
2

是否有简明的方式指向模板函数的所有实例而不使用宏?所有模板实例的C++单一函数指针

我有我想要跨多种类型的测试几个模板功能:

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,使用宏设置测试用例时效果不佳。

有没有办法做这样的事情:这似乎更清洁,除了定义SomeType的问题

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

。此问题(How to define typedef of function pointer which has template arguments)解释了如何定义指向模板化函数的指针;但是,要求指定模板参数。


对于澄清:设想function1function2,和function3每个测试一个不同的模板函数。每个函数都需要测试int,byte,char,double等。我想避免为每个函数明确地设置很多(即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); 
+0

XY-问题?我不明白你的意思。 –

+0

我试图找到解决这个问题的方法:http://stackoverflow.com/questions/38491608/test-c-template-class-using-catch-framework。具体来说,我试图用纯代码替换宏。该示例剥离了测试细节。想象一下'function1'测试模板化函数。 – Zack

+0

实际运行_what_? –

回答

5

你正在尝试与实现

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

将是可能的,如果SomeType可能是一个模板,模板ARG ument。但是,该标准不允许函数模板作为模板模板参数。

从C++ 11标准:

14.3.3模板模板参数

1模板的模板,参数A 模板参数应是一个类的名称模板或别名模板,用id表达式表示。

您最好的选择是使用函数而不是函数。例如:

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>(); 
} 
3

您可以通过类型擦除函子来完成它,就像一个在下面的例子:

#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的调用将被执行的问题。
此外,你不需要在一堆结构中移动你的函数来使用它们。

+0

非常有趣。你能解释更多关于这个部分:'(test.vec.emplace_back(&proto ),0)...'(尤其是'...')? – Zack

+0

@Zack省略号解包参数包'T'。这是一个窍门,可以解决折叠表达式到来的事实。确切的疑问是什么? – skypjack

+0

这是我多年来第一个C++项目。我之前没有看过那种语法,也不知道它的名称。 – Zack