【问题标题】:Conditional compilation of overloaded functions in template classes模板类中重载函数的条件编译
【发布时间】:2013-06-24 18:58:51
【问题描述】:

想象一个类(在 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;
}

即重载Invoke,然后回复条件编译,这样如果我实例化 FunctionWrapper&lt;void&gt;, 带有参数的 Invoke 版本永远不会被编译。我确定我在 Modern C++ 设计中读过如何做到这一点,但我不记得细节.....

【问题讨论】:

  • 我认为这是使用专业化的完美场景,即使你要求的可以做到,有什么好处?
  • A.我对如何做到这一点很感兴趣,因为我认为这可能是可能的,而且我想知道。 B. 这将节省我为 void 特化定义第二个基本相同的类定义。

标签: c++ templates overloading


【解决方案1】:

如果您尝试以这种方式实现函子,则设计中会存在许多明显的缺陷;我假设,并且您似乎在 cmets 上明确表示,该代码只是用于说明您的情况的示例。

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

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上的第一个答案,我希望我一切都好;如果没有,请给我一些反馈,不要对我太生气:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-03
    • 2018-03-25
    相关资源
    最近更新 更多