【问题标题】:Insert method's body conditionally using C++ templates使用 C++ 模板有条件地插入方法的主体
【发布时间】:2014-05-13 14:48:41
【问题描述】:

我对元编程完全是个菜鸟,我的问题很简单,但我还没有找到简单的答案。here 回答了类似的问题,但我无法将其转化为我的需要。

我有这样的课

class Program {

 public:

   Program(){}

   SetMatrixUniform(){

      CallSomeMethodX();

   }

    ~Program(){}

};

但我有这样的场景,我需要具有相同方法的同一个类,但在它们的主体中调用不同的函数。像这样:

 class Program {

 public:

   Program(){}

   SetMatrixUniform(){

      CallSomeMethodY();

   }

    ~Program(){}

};

我想要一个带有“true”参数的类的模板接口来选择在编译时放入类成员方法中的内容,而不是维护2个这样的类。

类似这样的:

  Program<true> myProg;   ///expands    CallSomeMethodX(); into  SetMatrixUniform()

同时:

  Program<false> myProg;   ///expands    CallSomeMethodY(); into  SetMatrixUniform()

我已经看到了声明类变体然后通过特化最终类扩展其中一个的示例。我想在不使用继承的情况下这样做,因为性能在这里非常重要。

【问题讨论】:

  • 您可能对this blog entry 感兴趣。这就是我通常用来解决这类问题的方法。同样适用于例如选择提供行为实现的特定基类。

标签: c++ templates metaprogramming


【解决方案1】:

这可以使用模板专业化

来解决

我们首先将Programm 声明为带有布尔参数的模板:

template<bool B>
struct Programm
{
    struct SetMatrixUniform()
    {
         std::cout << "General / Generic Implementation" << std::endl;
    }
};

现在我们可以为更具体的情况提供另一种实现/专业化,例如B == true

template<>
struct Programm<true>
{
    void SetMatrixUniform()
    {
       std::cout << "Sepcific Implementation For B == true" << std::endl;
    }
};

由于bool只能保持两种状态:true和false,如果模板实例化为false,则使用第一个实现,如果模板实例化为true,则使用第二个实现。


然而,这个解决方案有点冗长,需要两个人重新实现大部分功能。如果只是在某些方法上需要不同的行为,也可以直接比较B。例如:

template<bool B>
struct Programm
{
    void SetMatrixUniform()
    {
        if(B == true)
            //...
        else
            //...
    }
};

【讨论】:

  • 所以如果 Program 类有 40 个函数,这意味着我需要为您的第一个结构设置 40 个,为您的第二个结构设置 40 个?不能在方法层面解决吗?
  • 那么您的第二个示例将有效地仅生成一种方法并删除条件分支?
  • @MichaelIV 除了我提出的解决方案之外,在这种情况下也很常见的一种常见技术是将常见行为放在基类中,并从该基类派生出sepcialization。
  • @MichaelIV 你是什么意思?由于Programm&lt;false&gt;Programm&lt;true&gt; 是两个不同的类,所以第二种解决方案也会生成两个方法。然而,在这些方法中,我们会找到类似if(true == true)if(false == true) 的语句。如果条件消失,任何体面的编译器都可以对其进行优化。
  • @MichaelIV 关于继承:请了解事实。如果您 1) 不使用多态/虚拟方法 2) 不使用 RTTI,则继承不会产生任何类型的性能开销。
猜你喜欢
  • 1970-01-01
  • 2012-08-21
  • 1970-01-01
  • 2021-04-17
  • 2012-12-26
  • 1970-01-01
  • 1970-01-01
  • 2019-01-03
  • 1970-01-01
相关资源
最近更新 更多