基于编译时类型的调度

use*_*167 5 c++ templates

遵循“现代 C++ 设计”的技术,我正在实现一个具有各种编译时优化的持久性库。如果模板化成员变量派生自给定类,我希望能够将函数分派给该变量:

template<class T, template <class> class Manager = DefaultManager> class Data
{
private:
   T *data_;

public:
   void Dispatch()
   {
      if(SUPERSUBCLASS(Container, T))
      {
         data_->IKnowThisIsHere();
      }
      else
      {
         Manager<T>::SomeGenericFunction(data_);
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

其中 SUPERSUBCLASS 是一个编译时宏,用于确定对象继承。当然,在 T 确实从 Container 继承(或者 T 是内部类型等)的所有情况下,这都会失败,因为编译器正确地抱怨 IKnowThisIsHere() 不是数据成员,即使永远不会遵循此代码路径,使用 T = int 进行预处理后如下所示:

private:
   int *data_;

public:
   void Dispatch()
   {
      if(false)
      {
         data_->IKnowThisIsHere();
Run Code Online (Sandbox Code Playgroud)

编译器明显抱怨这段代码,即使它永远不会被执行。使用dynamic_cast的建议也不起作用,因为在编译时再次尝试进行类型转换是不可能的(例如使用T=double,std::string):

void Dispatch()
   {
      if(false)
      {
         dynamic_cast<Container*>(data_)->IKnowThisIsHere();

error: cannot dynamic_cast '((const Data<double, DefaultManager>*)this)->Data<double, DefaultManager>::data_' (of type 'double* const') to type 'class Container*' (source is not a pointer to class)
error: cannot dynamic_cast '((const Data<std::string, DefaultManager>*)this)->Da<sttad::string, DefaultManager>::data_' (of type 'struct std::string* const') to type 'class Container*' (source type is not polymorphic)
Run Code Online (Sandbox Code Playgroud)

我真的需要模拟(或者确实说服!)如果 T 确实从 Container 继承,则让编译器发出一组代码,如果不从 Container 继承,则发出另一组代码。

有什么建议么?

Nic*_*lli 3

正如Alexandrescu在他的《Modern C++ Design》一书中所提出的那样,重载对于实现编译时调度很有用。

您可以使用这样的类在编译时将布尔值或整数转换为类型:

template <bool n>
struct int2type
{ enum { value = n}; };
Run Code Online (Sandbox Code Playgroud)

以下源代码显示了可能的应用:

#include <iostream>

#define MACRO()   true  // <- macro used to dispatch 

template <bool n>
struct int2type
{ enum { value = n }; };

void method(int2type<false>)
{ std::cout << __PRETTY_FUNCTION__  << std::endl; }

void method(int2type<true>)
{ std::cout << __PRETTY_FUNCTION__  << std::endl; }

int
main(int argc, char *argv[])
{
    // MACRO() determines which function to call
    //

    method( int2type<MACRO()>()); 

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当然,真正完成这项工作的是 MACRO() 或作为元函数的更好实现