想象一个类(在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>
,
带有参数的Invoke版本永远不会被编译。我确定我在现代C ++设计中已经阅读了如何做到这一点,但我记不起细节......
答案 0 :(得分: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上的第一个答案,我希望我把一切都做对了;如果没有,请给我一些反馈,不要对我太不高兴:))