如果在普通的c ++中是静态的?

Gri*_*yan 12 c++ performance static c++11 static-if

问题简而言之:
如何static if在普通的c ++中实现c ++ 11中提出的功能?

历史和原始问题:
最近我提出了这样的问题.我需要一个Sender类似界面的类

class Sender
{
   void sendMessage( ... );
   void sendRequest( ... );
   void sendFile( ... );
   // lots of different send methods, not important actually
}
Run Code Online (Sandbox Code Playgroud)

在某些情况下,我需要创建一个DoubleSender,即这个类的一个实例,它会调用它的方法两次,即在调用时,比方说,一个sendMessage(...)方法,必须发送两次相同的消息.

我的解决方案:
第一种方法:
拥有一名isDouble成员,并在每次方法调用结束时进行检查

sendMessage(...) { ... if( isDouble ) { sendMessage( ... ); }
Run Code Online (Sandbox Code Playgroud)

好吧,我不想要这个,因为实际上我最近需要双重发布,这部分时间关键部分的代码将是98%被动.

第二种方法:从中
继承一个类,并实现其方法,如:DoubleSenderSender

void DoubleSender::sendMessage( ... )
{
   Sender::sendMessage(...);
   Sender::sendMessage(...);
}
Run Code Online (Sandbox Code Playgroud)

嗯,这是可以接受的,但需要很多不愉快的代码空间(真的很多,因为有很多不同的send..方法.

第三种方法:
想象一下我使用的是c ++ 11 :).然后我可以使这个类通用,并根据tempalte参数生成代码的必要部分static if:

enum SenderType { Single, Double };
template<SenderType T>
class Sender
{
   void sendMessage(...)
   {
      // do stuff
      static if ( T == Single )
      {
         sendMessage(...);
      }
   }
};
Run Code Online (Sandbox Code Playgroud)

这比以前的解决方案更简单,更容易阅读,不会产生额外的代码......它是c ++ 11,遗憾的是我不能在我的工作中使用它.

那么,这就是我提出问题的地方 - 如何static if在c ++中实现模拟?
此外,我将不胜感激任何其他有关如何解决我的原始问题的建议.
提前致谢.

seh*_*ehe 9

引用@JohannesSchaubLitb

我的static_if可以在gcc上运行,可以
用一些有限的方式来做到这一点

(另见这里)

这个技巧涉及GCC对C++ 11中Lambdas规范的特定解释.因此,它(可能)将成为违反标准的缺陷报告.这将导致该技巧不再适用于更新版本的GCC(它已经在4.7中不起作用).

有关Johanness的更多详细信息,请参阅下面的评论主题

http://ideone.com/KytVv:

#include <iostream>

namespace detail {
template<bool C>
struct call_if { template<typename F> void operator<<(F) { } };

template<>
struct call_if<true> {
  template<typename F>
  void operator<<(F f) { f(); }
};
}

#define static_if(cond) detail::call_if<cond>() << [&]

template<bool C, typename T>
void f(T t) {
  static_if(C) {
    t.foo();
  };
}

int main() {
  f<false>(42);
}
Run Code Online (Sandbox Code Playgroud)


mar*_*ark 7

为什么不将send实现作为sender类的策略并使用CRTP:

template<class Derived>
class SingleSenderPolicy
{
    public:
    template< class memFunc >
    void callWrapperImpl(memFunc f, ...)
    {
        static_cast<Derived *>(this)->f(...);
    }
};

template< class Derived >
class DoubleSenderPolicy
{
    public:
    template< class memFunc >
    void callWrapperImpl(memFunc f, ...)
    {
        static_cast<Derived *>(this)->f(...);
        static_cast<Derived *>(this)->f(...);
     }
};

template< class SendPolicy>
class Sender : public SendPolicy< Sender >
{
public:
    void sendMessage( ... )
    {
       // call the policy to do the sending, passing in a member function that
       // acutally performs the action
       callWrapperImpl( &Sender::sendMessageImpl, ... );
    }

    void doSomethingElse( ... )
    {
       callWrapperImpl( &Sender::doSomethingElseImpl, ... );
    }


protected:
    void sendMessageImpl(... )
    {
        // Do the sending here
    } 

    void doSomethingElseImpl(... )
    {
        // Do the sending here
    } 
};
Run Code Online (Sandbox Code Playgroud)

sendXXX您的类中的公共函数只是转发到调用包装器,传入实现实际功能的成员函数.该成员函数将根据SendPolicy类调用.CRTP保存使用bind来包装参数,并使用成员函数调用此指针.

使用一个函数它并没有真正减少代码量,但如果你有很多调用它可以帮助.

注意:此代码是提供可能解决方案的框架,尚未编译.

注意:Sender<DoubleSenderPolicy>并且Sender<SingleSenderPolicy>是完全不同的类型,并且不共享动态继承关系.


Pau*_* II 5

大多数编译器都会执行常量折叠和死代码删除,因此如果您编写一个常规的if语句,如下所示:

enum SenderType { Single, Double };
template<SenderType T>
class Sender
{
   void sendMessage(...)
   {
      // do stuff
      if ( T == Single )
      {
         sendMessage(...);
      }
   }
};
Run Code Online (Sandbox Code Playgroud)

生成代码时,if分支将被删除.

需要的static if是语句会导致编译器错误.所以说你有这样的东西(它有点伪造的代码):

static if (it == random_access_iterator)
{
    it += n;
}
Run Code Online (Sandbox Code Playgroud)

由于您无法调用+=非随机访问迭代器,因此即使删除了死代码,代码也始终无法使用常规if语句进行编译.因为编译器在删除代码之前仍会检查语法.static if如果条件不正确,使用编译器时将跳过检查语法.