8

以下のコードスニペットでは、

template<typename T1>
void func(T1& t)
{
    cout << "all" << endl;
}

template<typename T2>
void func(T2 &t)
{
    cout << "float" << endl;
}

// I do not want this
// template<> void func(float &t)

int main()
{
    int i; float f;
    func(i); // should print "all"
    func(f); // should print "float" 
    return 0;
}

float以外のタイプを渡すと「all」が出力され、floatを渡すと「float」と出力されるテンプレートを変更したいと思います。テンプレートの特殊化は必要ありません。代わりに、入力タイプに基づいてそれに応じて動作する部分的な特殊化があります。どうすればいいですか。前もって感謝します。

さて、私が現在直面しているシナリオは、次のように定義する必要があります。

template<typename T1>
void func(T1 &t)
{
    cout << "t1" << endl;
}

template<typename T2>
void func(T2 &t)
{
    cout << "t2" << endl;
}

次の呼び出しは「t2」を出力する必要があります

func(int) // print "t2"
func(float) // print "t2"
func(string) // print "t2"

次の呼び出しは「t1」を出力する必要があります

func(char) // print "t1"
func(xyz) // print "t1"
...
func(abc) // print "t1"

上記のようなある種のグループ化では、部分的な特殊化の実装を呼び出す必要があり、デフォルトの実装を呼び出す必要があります。

4

5 に答える 5

12

関数のオーバーロードをテンプレートと組み合わせることができます。そう:

#include <iostream>

template<typename T>
void func(T& t)
{
    std::cout << "all" << std::endl;
}

void func(float& f)
{
    std::cout << "float" << std::endl;
}

int main()
{
    int i; float f;
    func(i); // prints "all"
    func(f); // prints "float" 
    return 0;
}
于 2011-02-15T10:51:10.803 に答える
6

C++ では、関数を部分的に特殊化することはできません。

おそらく、これはあなたが意味する用語ではありません。テンプレートを使用boost::is_same<T1, T2>して、指定されたテンプレート パラメーターに基づいて条件付きロジックを実行できます。T次のように、他のタイプを使用する場所でも使用できtypeid(T).name()ます。

template <typename T>
void foo(T&) {
   if (boost::is_same<T, int>::value)
      std::cout << "int lol";
   else
      std::cout << typeid(T).name();
}

(ただし、 typeid().name() の使用はお勧めしません。その値は標準で指定されておらず、コードに記述された型、破損したシンボル、またはPokerfaceの歌詞とは異なる可能性があるためです。)

補遺他の回答者と同様に、私は個人的にテンプレートの特殊化自体を選択するか、単なる古い機能のオーバーロードを選択します。なぜあなたが彼らを嫌うのかわかりませんが、それが彼らの目的です。

于 2011-02-15T10:44:49.957 に答える
6

条件の型特性クラスを作成します。

template<class T>
struct IsIntFloatOrString {
  enum { value = boost::is_same<T, int>::value
              or boost::is_same<T, float>::value
              or boost::is_same<T, string>::value };
};

boost::enable_ifと disable_ifを使用します。

template<typename T1>
typename boost::enable_if<IsIntFloatOrString<T1> >::type
func(T1 &t) {
  cout << "t1" << endl;
}

template<typename T2>
typename boost::disable_if<IsIntFloatOrString<T2> >::type
func(T2 &t) {
  cout << "t2" << endl;
}
于 2011-02-15T21:16:22.000 に答える
3

Tomalak が彼の回答で既に述べたように、テンプレート関数を部分的に特殊化することはできませんが、関数をテンプレート クラスの静的メンバー関数に変更すると、それを行うことができます。

ただし、より良いアプローチは、関数のオーバーロードです。

于 2011-02-15T10:56:31.730 に答える
0

これは、任意の数の条件の場合にa and !b and !c醜い構文なしで機能させる方法です。enable_if

部分的な特殊化が関数ではなくクラスで機能することがわかっている場合は、クラスを使用しましょう。人々から隠す必要がありますが、使用できます。

OK、コード:

#include <type_traits>
#include <iostream>


template <typename T>
class is_int_or_float : public std::integral_constant<bool, std::is_same<T, int>::value || std::is_same<T, float>::value> {
};


template<typename T, typename Enable = void> //(2)
struct Helper {
    static void go(const T&) {
                std::cout << "all"<< std::endl;
        }
};

template<typename T>
struct Helper<T, typename std::enable_if<is_int_or_float<T>::value>::type> { // (3)
        static void go(const T&) {
                std::cout << "int or float" << std::endl;
        }
};

template<typename T>
struct Helper<T, typename std::enable_if<std::is_pointer<T>::value>::type> { // (3)
        static void go(const T&) {
                std::cout << "pointer" << std::endl;
        }
};

template<typename T>
void func(const T& arg) {
        Helper<T>::go(arg); // (1)
}
int main() {
        char c;
        int i;
        float f; 
        int* p;
        func(c);
        func(i);
        func(f);
        func(p);
}

(1) まず、すべてのタイプのコール ヘルパーに対して。関数の専門化はありません。
(2) ここで、仮引数を 1 つ追加します。void デフォルトは(3)であるため、呼び出しvoid時に指定する必要はありませんTT重要なことの 1 つは、 2 回以上許可しないことです。

ノート:

  1. デフォルトの型を std::true_type に変更することもできます。その後、取り除くことができますstd::enable_if(std::enable_if<some_trait<T>::value>は just に変更されますsome_trait<T>::type)。どちらかわかりません

  2. このコードは、C++11 の型特性を使用しています。C++11 がサポートされていない場合は、独自のトレイトを作成するか、型トレイトを使用できます。boost

実際の例

于 2013-08-18T19:35:17.577 に答える