【问题标题】:Substitution of void as parameter to templated method将 void 作为参数替换为模板方法
【发布时间】:2014-11-16 12:58:11
【问题描述】:

在我的代码中,我有一个注册其他类的方法的类:

#include <iostream>
using namespace std;

template< typename C>
  class Reg {
  public:
    template< typename R, typename A>
      void register_f( string name, R ( C:: *method_p ) ( A)) { /*registration process*/ }

//    template< typename R>
//      void register_void_f( string name, R ( C:: *method_p ) ( void)) { /*registration process*/ }
  };

  class A {
  public:
      int f( void) { return 1; }
      void g( int x) { /* some code*/ }
  };


  int main() {
      Reg< A> r;

      r.register_f( "g", &A::g);
/*1*///  r.register_f( "f", &A::f);
/*2*///  r.register_f< int, void>( "f", &A::f);
/*3*///  r.register_void_f< int>( "f", &A::f);

      return 0;
  }

http://ideone.com/X8PNLC

取消注释行 /* 2 */ 给我一个错误:

模板参数推导/替换失败:

代替'template void register_f(std::string, R (C::*)(A)) [with R = R; A = A; C = A] [其中 R = int; A = void]':

错误:无效的参数类型'void'

Line /* 1 / 与 / 2 */ 相同,但错误信息不那么丰富。

我知道要解决问题,我可以使用方法 register_void_f,但我不想这样做,因为 register_f 是我最终 API 的一部分。

问题>如何在不引入register_void_f的情况下修复编译错误?

我有一个想法用部分特化 register_f 解决它,但我不知道该怎么做,因为在 C++ 中你不能部分特化模板化方法。

PS>我不能使用 C++11。

【问题讨论】:

    标签: c++ templates void member-function-pointers c++03


    【解决方案1】:

    不要使用 void 来表示没有参数,使用 nothing - 像这样:

    template< typename R>
         void register_void_f( string name, R ( C:: *method_p ) ()) { /*registration process*/ }
    

    【讨论】:

    • 问题是如何在没有 register_void_f 的情况下做到这一点。我认为使用或不使用 void 没有区别。
    • 用不带参数的版本重载register_f怎么样?
    • 你的意思是使用继承?
    【解决方案2】:

    重载你的函数:

    void foo( int ) {}
    double bar() { return 3.14; }
    
    template< class R, class A >
    void test(  R ( *method_p ) (A)) {  }
    template< class R >
    void test(  R ( *method_p ) ()) {  }
    
    int main(){
      test(foo);
      test(bar);
    }
    

    live example

    将其转换为方法应该很容易。

    【讨论】:

    • 我认为很难专攻它。
    • @ValentinT。压倒一切不是专业化。专业化是不同的,通常对函数来说是个坏主意(你最好重写)。如果您需要花哨的专业化,您通常会转发到一个您拥有完整专业化机制的课程,而不是残缺且令人困惑的功能模板专业化。
    • 你说得对。有了这些模板,我几乎忘记了我们可以简单地覆盖方法。
    【解决方案3】:

    您可以使用以下内容:

    template< typename C> class Reg;
    
    template <typename C, typename F> struct helper;
    
    template <typename C, typename R, typename A>
    struct helper<C, R (C::*)(A)>
    {
        void operator() (Reg<C>& reg, const std::string& name, R (C::*method)(A)) const { /* Your implementation */}
    };
    
    template <typename C, typename R>
    struct helper<C, R (C::*)()>
    {
        void operator() (Reg<C>& reg, const std::string& name, R (C::*method)()) const { /* Your implementation */}
    };
    
    
    template< typename C>
      class Reg {
      public:
        template< typename F>
          void register_f(const std::string& name, F method) { helper<C, F>()(*this, name, method);  /*registration process*/ }
    
      };
    

    并以这种方式使用它:

    Reg< A> r;
    
    r.register_f( "g", &A::g);
    r.register_f( "f", &A::f);
    r.register_f<int (A::*)(void)>( "f", &A::f);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-24
      • 1970-01-01
      • 2016-01-11
      • 2017-11-19
      相关资源
      最近更新 更多