【问题标题】:Is it possible to write c++ template/macros to check whether two functions have the same signatures是否可以编写c ++模板/宏来检查两个函数是否具有相同的签名
【发布时间】:2013-01-10 13:55:55
【问题描述】:

是否可以编写 c++ 模板/宏来检查两个函数是否具有相同的签名(返回类型和参数列表)?

这是我想如何使用它的一个简单示例:

int foo(const std::string& s) {...}
int bar(const std::string& s) {...}

if (SAME_SIGNATURES(foo, bar))
{
    // do something useful... make Qt signal-slot connection for example...
}
else
{
    // signatures mismatch.. report a problem or something...
}

那么它有可能以某种方式还是只是一个白日梦?

附: 其实我对 c++ 2003 标准很感兴趣。

【问题讨论】:

    标签: c++ templates c-preprocessor sfinae


    【解决方案1】:

    C++11 解决方案

    无需自己编写任何模板。

    您可以将decltypestd::is_same 一起使用:

    if (std::is_same<decltype(foo),decltype(bar)>::value )
    {
        std::cout << "foo and bar has same signature" << std::endl;
    }
    

    这里decltype返回表达式的类型,在这种情况下是函数,std::is_same比较两个类型,如果两者都返回true相同,否则false


    C++03解决方案

    在C++03中,你没有decltype,所以你可以实现重载的函数模板为:

    template<typename T>
    bool is_same(T,T) { return true; }
    
    template<typename T, typename U>
    bool is_same(T,U) { return false; }
    

    现在您可以将其用作:

    if (is_same(foo, bar))
    {
        std::cout << "foo and bar has same signature" << std::endl;
    }
    

    现在在这种情况下is_same 是一个函数模板,而不是类模板。所以它在运行时而不是编译时进行评估。所以这会报错:

    int a[is_same(foo,bar) ? 10 : 20]; //error (in Standard C++03)
                                       //the size must be known at compile-time!
    

    但是,如果您需要在编译时了解它,那么您必须做更多工作,并将功能实现为:

    typedef char same[1];
    typedef char different[2];
    
    template<typename T>
    same& is_same_helper(T,T);  //no need to define it now!
    
    template<typename T, typename U>
    different& is_same_helper(T,U); //no definition needed!
    
    #define is_same(x,y)   (sizeof(is_same_helper(x,y)) == sizeof(same))
    

    现在将其用作:

    if (is_same(foo, bar))
    {
        std::cout << "foo and bar has same signature" << std::endl;
    }
    

    您也可以在编译时使用它。这样你就可以写了:

    int a[is_same(foo,bar) ? 10 : 20]; //okay
    

    希望对您有所帮助。

    【讨论】:

    • decltype 是在 C++11 标准中引入的。 c++ 2003 可以吗?
    • 将 foo 和 bar 作为参数传递给模板函数,这是自动推断类型的另一种方法。
    • 需要显式实例化值。另一种方法是让 is_same(T,U) 返回 false,而重载 is_same(T,T) 返回 true。
    • @MarcGlisse:很好。我会选择那个。让我编辑一下。
    • 使重载返回大小为 1 和 2 的类型,因此您可以在编译时使用 sizeof 来区分。
    【解决方案2】:

    这样的事情怎么样:

    #include <iostream>
    
    void a(int)
    { }
    
    void a2(int)
    { }
    
    void b(float)
    { }
    
    struct true_type
    { enum { value = 1 }; };
    
    struct false_type
    { enum { value = 0 }; };
    
    template <typename T, typename U>
    false_type
    is_same_sig (T, U)
    { return false_type (); }
    
    template <typename T>
    true_type
    is_same_sig (T, T)
    { return true_type (); }
    
    int
    main ()
    {
      std::cout << is_same_sig (a, a2).value
                << is_same_sig (a, b).value
                << "\n";
    }
    

    【讨论】:

      【解决方案3】:

      这是另一个适用于 C++03 的替代解决方案:

      #include <iostream>
      
      using namespace std;
      
      template<typename F1, typename F2>
      bool same_signature(F1 const&, F2 const&)
      {
          return false;
      }
      
      template<typename F>
      bool same_signature(F const&, F const&)
      {
          return true;
      }
      
      void test1(std::string, int) { }
      void test2(std::string, int) { }
      void test3(std::string, double) { }
      
      int main()
      {
          cout << same_signature(test1, test2);
          cout << same_signature(test1, test3);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-11
        • 2015-08-24
        • 1970-01-01
        • 2016-01-30
        • 1970-01-01
        • 1970-01-01
        • 2014-02-03
        • 2017-11-02
        相关资源
        最近更新 更多