检测模板化方法和自由函数的存在

时间:2012-02-25 10:29:46

标签: c++ c++11 template-specialization

我有一套专门的模板。现在我想为两种情况创建专门的模板:

  1. 如果某个类/结构中存在某种方法(检测名称就足够了)。

  2. 如果存在某个免费功能(在这种情况下,应检测名称和部分签名)。

  3. 问题是,自由函数和类方法都会被模板化。这是一种序列化体系结构,我有多种方法可以序列化,因此方法/函数的模板参数将是专门的其他模板提供的序列化策略。我无法将策略作为抽象基础,因为后来其他模板化方法将被调用,虚拟和模板不会混合。

    这是我需要的一个例子:

    template<typename T>
    struct strategy1 {};
    
    template<>
    struct strategy1<char> {
      void call() {
        // Do char specific stuff
      }
    };
    
    class foo_specialized {
    /* ... */
    };
    
    template<>
    struct strategy1<foo_specialized> {
      void call() {
        // do foo_specialized stuff
      }
    };
    
    class foo_method {
    public:
      template< Typename T>
      void serialize( T & t ) {
        // use T here to do stuff
      }
    };
    
    /* This should be used for foo_method */
    template< typename T >
    struct strategy1</* don't know what to put here */>
      struct strategy1_helper{
        template<typename T2>
        void call( T2 t ) {
           // do stuff with t
        }
       };
    
      void call( const T & t ) {
        t.serialize( strategy1_helper() );
      } 
    };
    
    class foo_function {
    /* ... */
    };
    
    template<typename T>
    void serialize( const foo_function & foo, T & t ) {
      // use T here
    }
    
    /* This should be used for foo_function */
    template< typename T >
    struct strategy1</* don't know what to put here */>
      struct strategy1_helper{
        template<typename T2>
        void call( T2 t ) {
           // do stuff with t
        }
       };
    
      void call( const T & t ) {
        serialize( t, strategy1_helper() );
      } 
    };
    

    是否有可能让模板解析机制根据实际提供的参数选择这两个最后一个特化?或者是否有更清洁的设计来实现这一目标?

    我可以轻松使用C ++ 11提供的类型特征和元编程功能,所以我不必自己完成SFINAE步骤。

1 个答案:

答案 0 :(得分:2)

该解决方案需要使用SFINAE来检测所述成员函数的潜在返回类型。如果对成员指针的访问失败,该技巧使用省略号重载。

正确实现也需要一些宏样板。我有这样的实现:

https://github.com/jfalcou/boosties/tree/master/introspection/boost

现在用C ++ 11的思维方式,其中一些当然可以变成基于decltype的检测,但是当你需要一种提取成员名称的方法时仍需要宏。