4

是否可以编写 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...
}

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

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

4

3 回答 3

17

C++11 解决方案

无需自己编写任何模板。

您可以decltype使用std::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

希望有帮助。

于 2013-01-26T21:02:43.520 回答
3

像这样的东西怎么样:

#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";
}
于 2013-01-26T21:25:59.007 回答
2

这是另一个适用于 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);
}
于 2013-01-26T21:14:45.123 回答