14

是否可以创建通用 C++ 函数foo

foo(Object bar, Object fred)
{
    //code
}

其中如果两个对象被识别,它们被比较并返回一个比较值,否则返回一些其他值以指示比较是不可能的?

我问在泛化排序类的情况下,在这种情况下你可以使用这个方法,当你派生你想要排序的新对象时,你添加到这个 foo 函数中,一个方法来对新类型的 Object 进行排序。

4

7 回答 7

32

使用模板,定义函数的两个版本,一个参数类型相同,一个参数可以不同:

#include <string>
#include <iostream>
using namespace std;

template<typename Type>
void func(Type, Type)
{
    cout << "same" << endl;
}

template<typename TypeA, typename TypeO>
void func(TypeA, TypeO)
{
    cout << "different" << endl;
}

int main()
{
    func(5, 3);                     // same
    func(5, 3.0);                   // different
    func(string("hello"), "hello"); // different
    func(5.0, 3.0);                 // same
    return 0;
}

输出

same
different
different
same
于 2012-05-14T07:48:11.957 回答
18

我认为您急需模板
您可以编写一个模板函数,然后为上述类型编写一个特化,以便在需要时做一些特定的事情。

于 2012-05-14T07:22:50.720 回答
5
template<class Type1, class Type2>
void foo(Type1 t1, Type2 t2)
{
   // put code here for function
}

称为

foo<std::string, int> ("hello", 10);
于 2012-05-14T07:37:25.520 回答
3

很可能您需要按照其他人的建议使用模板:

template <class T>
return_type func(T const& l, T const& r)
{
   ...
}

因为当泛型函数实现的操作对特定类型没有意义时,您通常希望编译失败,所以您可以使用条件定义(在下面的示例中为 is_arithmetic):

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>

template <class T>
typename boost::enable_if<boost::is_arithmetic<T>, return_type>::type
func(T const& l, T const& r)
{
    ...
}

或代码中的静态断言以产生相同的结果:

#include <boost/type_traits/is_arithmetic.hpp>

template <class T>
return_type func(T const& l, T const& r)
{
    static_assert(boost::is_arithmetic<T>::type::value, "incompatible types");
    ...
}
于 2012-05-14T07:48:39.577 回答
1

我要在这里伸出我的脖子说你不需要模板来做到这一点。我并不是说不要使用它们,只是这取决于你想要做什么,还有其他选择。

听起来您想要的能够比较两个通用对象,前提是它们遵守一组通用的基本规则。您实际上可以使用传统继承或使用模板来实现这一点。您想要的选择取决于您需要它的灵活性以及您是否希望在运行时或编译时做出某些决定。如果是后者 - 即您想了解投射错误等 - 然后选择模板。

无论哪种方式,您的对象都必须遵守一些基本规则来比较它们,并最好将其封装 - 这样您的比较器将是通用的。或者您必须为每个对象比较编写不同的比较器。虽然听起来后者是你想要的,但要小心不要让太多的类实现渗入比较器函数,从而破坏封装。

根据我自己的经验,直接使用模板方法有时会导致大量臃肿、混乱的代码,难以阅读、调试和维护。首先仔细看看你的设计和你真正需要的东西。

于 2012-05-14T08:23:51.753 回答
0

OP 似乎想知道这两个对象是否具有可比性。您可以使用模板专业化来实现这一点(注意:这不能在 VC 10 上编译,但在 g++ 4.7 上可以)。唯一的细微差别是您希望此功能

它们被比较并返回一个比较值,否则返回一些其他值以指示无法进行比较

但是您需要定义某种结构来表示无法进行比较;使用幻数“-500”或任何不好的风格。或者,您可以抛出一个错误,并允许它被捕获并处理。

struct NoCompare{};

template <typename U1, typename U2>
static auto compare2(const U1 & u1, const U2 & u2) -> decltype(u1 == u2)
{ 
    cout << "Comparable" << endl;
    return u1 == u2;
}

static int compare2(...) 
{ 
    // Comparison not supported - return whatever value you want. (change the return type as appropriate)
    cout << "Not comparable" << endl;
    return -500;
}

int main()
{
    int a = 5, b = 3, c = 3;
    NoCompare dns;
    cout << compare2(a, b) << endl;
    cout << compare2(dns, b) << endl;
    cout << compare2(c, b) << endl;

    return 0;
}

输出:C:\MinGW\MinGW>a 可比较 0 不可比较 -500 可比较 1

于 2012-05-14T09:16:08.643 回答
0

您似乎指的是 Common Lisp / CLOS 样式的通用函数,它们执行多个动态调度。C++ 使用方法进行单次动态调度,但仅使用函数进行单次静态调度。所以答案是否定的。C++ 目前不支持这个。多年来一直有人提议将其添加到语言中,但尚未发生。

于 2017-02-07T06:34:47.263 回答