14

一般的な C++ 関数を作成することは可能fooですか?

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

2 つのオブジェクトが認識された場合、それらが比較され、比較値が返されます。それ以外の場合は、比較が不可能であることを示すために他の値が返されますか?

並べ替えクラスをジェネリック化する場合は、このメソッドを使用できます。並べ替えたい新しいオブジェクトを派生させるときは、この foo 関数に、新しい型のオブジェクトを並べ替えるメソッドを追加します。

4

7 に答える 7

32

テンプレートを使用して、関数の 2 つのバージョンを定義します。1 つはパラメーターが同じ型で、もう 1 つはパラメーターが異なる可能性があります。

#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

ここで首を突っ込んで、これを行うのにテンプレートは必要ないと言います。それらを使用しないと言っているわけではありませんが、まさにあなたがやりたいことに応じて、代替手段があるということです。

あなたが望んでいるように聞こえるのは、2 つの汎用オブジェクトが共通の基本ルールに準拠しているという条件で比較する機能です。これは、従来の継承またはテンプレートを使用して実際に実装できます。どちらを選択するかは、どの程度の柔軟性が必要か、また実行時に決定を行うかコンパイル時に行うかによって決まります。後者の場合、つまり、キャストエラーなどを見つけたい場合は、テンプレートを使用してください。

いずれにせよ、オブジェクトは、比較方法に関するいくつかの基本的な基本ルールに準拠する必要があり、できればそれをカプセル化する必要があります。このようにして、コンパレーターは一般的になります。または、オブジェクトの比較ごとに異なるコンパレータを作成する必要があります。後者が望ましいように思えますが、クラス実装の多くがコンパレーター関数に浸み出して、カプセル化が壊れないように注意してください。

私自身の経験から、テンプレート アプローチに直行すると、読み取り、デバッグ、保守が困難な大量の混乱したコードが作成されることがあります。最初にデザインと実際に必要なものをよく見てください。

于 2012-05-14T08:23:51.753 に答える
0

OPは、2つのオブジェクトが同等かどうかを知りたいようです。テンプレートの特殊化を使用してこれを実現できます (注: これは 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 に答える