9

クラスがあるとします:

template <class Type>
class A
{
public:
    void function1(float a, Type b);
    void function1(float a, float b);
};

次のようにクラスをインスタンス化します。

A<int> a;

このクラスには、次のパラメータを持つ 2 つのオーバーロードされた関数があります: (float a, int b); (フロート a、フロート b);

しかし、次のようにクラスをインスタンス化すると:

A<float> a;

コンパイルエラーが発生します:

メンバー関数が再宣言されました。

そのため、Type のタイプによっては、コンパイラに次のような関数を定義させたくない (または望まない) ようにします。

template <class Type>
class A
{
public:
    void function1(float a, Type b);

    #if Type != float
    void function1(float a, float b);
    #endif
};

しかし、もちろん、上記の構文は機能しません。そのようなタスクを C++ で実行することは可能ですか? 可能であれば、例を挙げてください。

4

3 に答える 3

9

あなたはいくつかを使うことができますC++11 std::enable_if

template <class Type>
class A
{
public:
    template<typename t = Type, 
       typename std::enable_if<!std::is_same<t, float>::value, int>::type = 0>
    void function1(float a, Type b) {
    }

    void function1(float a, float b) {
    }
};
于 2012-05-01T09:46:00.567 に答える
8

テンプレートの特殊化を使用できます。

template <class Type>
class A {
public:
    void function1(float a, Type b) {
    }
    void function1(float a, float b) {
    }
};

template <>
class A<float> {
public:
    void function1(float a, float b) {
    }
};

// ...

A<int> a_int;
a_int.function1(23.4f, 1);
a_int.function1(23.4f, 56.7f);

A<float> a_float;
a_float.function1(23.4f, 56.7f);

- - 編集 - -

多数の共通関数がある場合は、次のようにすることができます。

class AImp {
public:
    void function1(float a, float b) {
    }
    void function1(float a, double b) {
    }
    void function1(float a, const std::string& b) {
    }
    // Other functions...
};

template <class Type>
class A : public AImp {
public:
    void function1(float a, Type b) {
    }
    using AImp::function1;
};

template <>
class A<float> : public AImp {
};

// ...

A<int> a_int;
a_int.function1(23.4f, 1);
a_int.function1(23.4f, 56.7f);
a_int.function1(23.4f, 56.7);
a_int.function1(23.4f, "bar");

A<float> a_float;
a_float.function1(23.4f, 56.7f);
a_float.function1(23.4f, 56.7);
a_float.function1(23.4f, "bar");
于 2012-05-01T09:22:17.337 に答える
2

SFINAE を使用します。

#include <iostream>
#include <type_traits>

template <typename Type>
struct Foo {
    template <typename T = Type>
    void function1(float a, float b, typename std::enable_if<!std::is_same<T, float>::value>::type *c = 0) {
        std::cout << "float\n";
    }
    void function1(float a, Type b) {
       std::cout << "type\n";
    }
};

int main() {
    Foo<float> f;
    f.function1(1, 1);
    f.function1(1.0f,1.0f);
    Foo<int> g;
    g.function1(1,1);
    g.function1(1.0f,1.0f);
    g.function1(1.0,1.0); // warning!
}

出力:

type
type
type
float
type

関数テンプレートで既定のテンプレート パラメーターを許可するには、C++11 モードが必要です。また、 と を取得enable_ifするis_sameこともできますが、enable_if代わりに Boost から取得することもできます。

警告!" 元のコードg.function1(1.0,1.0);があいまいだったからです。現在は、非テンプレート オーバーロードが優先されます。あなたはそれを再び曖昧にすることができます

    template <typename T = Type>
    void function1(float a, Type b, typename std::enable_if<true>::type *c = 0) {
       std::cout << "type\n";
    }
于 2012-05-01T10:09:38.153 に答える