2013-06-27 109 views
2

想象一个类(在VS2010,没有可变参数模板这里对不起)条件编译

template <class Arg> 
class FunctionWrapper 
{ 
public: 
     void Invoke(Arg arg){_fn(arg)}; 
private: 
     std::function<void(Arg)> _fn; 
} 

然后我就可以做如

FunctionWrapper <int> foo; foo.Invoke(4); 

而且这个编译好。但这并不:

FunctionWrapper <void> foo; foo.Invoke(); 

现在,我可以解决这个使用模板特殊化。但我也想知道是否有一个办法可以解决这个问题的另一种方式....

template <class Arg> 
class FunctionWrapper 
{ 
public: 
     void Invoke(void){_fn()};     // } overloaded 
     void Invoke(Arg arg){_fn(arg)};    // } 
private: 
     std::function<void(Arg)> _fn; 
} 

即超载调用,然后在条件编译答复,这样,如果我实例 FunctionWrapper<void>, 调用的版本与参数永远不会被编译。我确定我在Modern C++设计中读到了如何做到这一点,但我不记得细节.....

+0

我认为这是使用专业化的完美场景,即使你问的问题可以做,有什么好处? –

+0

答:我对如何做到这一点感兴趣,因为我认为这可能是可能的,而且我想知道。 B,它可以节省我为虚空专业定义第二个,大体上相同的类定义。 –

回答

0

如果您试图通过这种方式实现仿函数,那么会出现一些明显的缺陷在设计中;我认为,你似乎在评论中明确表示,代码只是一个用来说明你的情况的例子。

这里有几个解决方案的问题:

template<class T> 
struct Trait{ 
    typedef T type; 
    typedef T mock_type; 
}; 
template<> 
struct Trait<void>{ 
    typedef void type; 
    typedef int mock_type; 
}; 

template <class Arg> 
class FunctionWrapper 
{ 
public: 
     void Invoke(void){_fn();} 
     void Invoke(typename Trait<Arg>::mock_type arg){_fn(arg);} 
     boost::function<void(typename Trait<Arg>::type)> _fn; 
private: 
}; 

template <class Arg> 
class FunctionWrapper2 
{ 
public: 
    FunctionWrapper2(const boost::function<void(Arg)> arg) : Invoke(arg){} 
    const boost::function<void(Arg)> Invoke; 
}; 

int main(int argc, _TCHAR* argv[]) 
{ 

    FunctionWrapper<int> cobi; 
    cobi._fn = &countOnBits<int>; 
    cobi.Invoke(5); 

    FunctionWrapper<void> cobv; 
    cobv._fn = &func; 
    cobv.Invoke(); 

    FunctionWrapper2<int> cobi2(&countOnBits<int>); 
    cobi2.Invoke(5); 

    FunctionWrapper2<void> cobv2(&func); 
    cobv2.Invoke(); 
    //[...] 
} 

当然,我不是说我写的是好的代码,至于这个问题它只能用于提供工作结构的例子。

你的尝试的问题是,虽然函数void Invoke(Arg arg){_ fn(arg)};实际上没有在你实例化FunctionWrapper的时候被编译(并且不要试图用参数调用Invoke函数),它会被语法检查;当然Invoke(void arg)不是你的编译器会接受的东西!

这是我在stackoverflow上的第一个答案,我希望我的一切都正确;如果没有,请给我一些反馈,不要太难过我:)