2017-07-19 96 views
1

在下面的代码中,我有一个名为data的变量。它内部包含一个函数来稍后调用它们。假设data在另一个库中定义,我无法更改其类型。我为其中每个已知函数的一部分(s3)的成员分配模板函数,并且在调用函数时必须给出一部分函数(true)。我能不能通过这样的事情:如何用已知的函数参数来避免lambda函数?

data[0]=test_func(?,s3); // error 

相反,我要传递一个lambda函数给它:

data[0]=[](bool b){test_func(b,s3);}; // ok 

但lambda函数看起来并不整齐尤其是当我们有100数组这些任务。有没有办法通过以任何方式更改test_func来避免lambda函数?即使使用test_func内的lambda也对我来说是可以的,因为它只写了一次。

#include <iostream> 
#include <functional> 

template<typename F> 
void test_func(bool b,F f) 
{ 
    if(b) 
     f(); 
} 

void s1() 
{ 
    std::cout<<"s1 \n"; 
} 

void s2() 
{ 
    std::cout<<"s2 \n"; 
} 

void s3() 
{ 
    std::cout<<"s3 \n"; 
} 

int main() 
{ 
    test_func(true,s1); 
    test_func(true,s2); 
    test_func(false,s1); 
    test_func(true,s2); 
    ///////////////// 
    std::function<void(bool)> data[100]; 
    // data=test_func(?,s3); // error 
    data[0]=[](bool b){test_func(b,s3);}; // ok 
    data[0](true); 
    return 0; 
} 
+0

这不只是'的std ::函数 foo(F f){return [](bool b){test_func(b,f); }; }'? – melpomene

+0

现在,最好的解决方案是简单地使用lambda函数。 'std :: bind'试图做到这一点,但使用它需要学习它的迷你语言(对于任何读取代码的人),并且往往会使编译器难以优化。此外,它最终只比lambda函数短。 – Justin

+0

@melpomene,你如何适应这个代码? – ar2015

回答

2

如果你想避免lambda功能完全,以及templates你可以使用的功能(类operator()):

typedef void (&F)(void); 
class TestFunc { 
    F f; 
    public: 
    TestFunc(const F f) : f(f) {} 
    void operator()(bool B) const { 
     if(B) f(); 
    } 
}; 

TestFunc(s3)分配它。只是typedefF向功能型,不需要模板:

typedef void (&F)(void); 

,并彻底清除模板 - 我通常喜欢少模板如果可能的话,但是这味道。如果您需要不同的功能签名支持,则只会真正调用模板。

要使用标准库功能只是改变typedef

typedef std::function<void(void)> F; 
+0

'template '? '错误:ISO C++禁止声明'功能'没有类型' – ar2015

+0

非常感谢。这个解决方案可以扩展到'std :: function'吗? – ar2015

+0

我添加了一些'const'正确性,如果它很重要。 – kabanus

1

你可以创建一个辅助函数的拉姆达:

#include <iostream> 
#include <string> 
#include <functional> 
#include <vector> 

template<typename F> 
void test_func(bool b,F f) { 
    if(b) { 
     f(); 
    } 
} 

std::function<void(bool)> wrap_function(const std::function<void(void)> &f) { 
    return [f](bool b){test_func(b,f);}; 
} 

void s1() { 
    std::cout<<"s1 \n"; 
} 

int main() { 
    std::vector<std::function<void(bool)>> data; 

    data.push_back(wrap_function(s1)); 

    data[0](true); 
} 

而且你应该使用std::vectorstd::array或其他性病的容器而不是std::function<void(bool)> data[100]

2

如果每个s_n是一个常规函数具有相同的签名,您可以从test_func中删除f参数,而是将该函数本身作为模板参数传递。

template<void(&f)()> 
void test_func(bool b) 
{ 
    if(b) 
     f(); 
} 

而且使用这样的:

data[0] = test_func<s1>; 

函数指针和引用明确允许作为模板非类型参数由[temp.param/4]

A non-type template-parameter shall have one of the following (optionally cv-qualified) types:

[...]

  • pointer to object or pointer to function,
  • lvalue reference to object or lvalue reference to function,
+0

喜兄弟再次。它可以通过std :: function而不是指针来完成吗? – ar2015

+0

@ ar2015 - 不可以,因为对于初学者来说,一个'std :: function'不能是一个常量表达式。它具有允许类型擦除的状态。从某种意义上说,函数指针只能在编译时“固定”,因此才是允许的。 – StoryTeller

+0

这是否意味着指针在优化方面优于'std :: function'? – ar2015