5

スペシャライゼーションを複数回作成しないように、スペシャライゼーションをグループ化しようとしています。たとえば、以下のコードでは、foo :: func()の実装の1つのケースとして、「float」と「double」を特殊化しようとしています。次に、「bool」の別の実装を使用します。

template<typename T> struct foo;

template<typename T> struct bar;
template<> struct bar<float> { typedef float Type; };
template<> struct bar<double> { typedef double Type; };

/* specialize for float and double here */
template<typename T> struct foo<typename bar<T>::Type> {
    static void func() { ... }
};

template<> struct foo<bool> {
    static void func() { ... }
};

これはGCC4.4.3でエラーになります。(これはターゲットコンパイラです。これは、Ubuntu Server 10.04 LTSの在庫であり、残り3年と言われています。)エラーは次のとおりです。

foo.cpp:8: error: template parameters not used in partial specialization:
foo.cpp:8: error:         ‘T’

このエラーは、fooの最初の特殊化(「float」および「double」の場合)を示しています。

ここで違反しているC++の部分がわかりません。章と節を知っている人がいれば、それをいただければ幸いです。また、誰かが同じ目標を達成する別の方法を知っている場合(不必要に冗長なコードを使用せずに、特定のタイプのグループの特殊化を再利用する)、提案をいただければ幸いです。

4

2 に答える 2

6
template<typename T> struct foo<typename bar<T>::Type> {
    static void func() { ... }
};

T推定不可能なコンテキストで使用しているため、コンパイラはTの値を知っていても推定できませんbar<T>::Type

あなたが書くと仮定すると、

foo<double> foodouble;

では、インスタンス化の際にbarどちらが専門化されているかが選択されると思いますか? これは、次のようなネストされた型として定義される別の特殊化が存在しないことをコンパイラが確認できる場合にのみ、妥当と思われます。doublefoobardouble

template<> struct bar<int> { typedef double Type; };

bar<double>::Typebar<int>::Type両方を与えdoubleます。要するに、 の特殊化が無限に存在する可能性がありbar、そのすべてがネストされた型として提供される可能性があり、コンパイラがクラス templateのテンプレート引数を一意doubleに推測することを不可能にします。bar


SFINAEは次のように使用できます。

#include <iostream>

template<typename T> struct bar { typedef void type; };
template<> struct bar<float> { typedef bar<float> type; };
template<> struct bar<double> { typedef bar<double> type; };

template<typename T> 
struct foo : bar<T>::type
{
    static void func() 
    { 
        std::cout << "primary template for float and double" << std::endl; 
    }
};

template<> 
struct foo<bool> 
{
    static void func() 
    { 
       std::cout << "specialization for for bool" << std::endl; 
    }
};

int main()
{
     foo<float>::func();
     foo<double>::func();
     foo<bool>::func();
}

出力 (オンライン デモ):

primary template for float and double
primary template for float and double
specialization for for bool

struct foo : bar<T>::typeもはや専門分野ではないことに注意してください。プライマリ テンプレートです。floatまた、 、doubleおよび以外の型引数を持つクラス テンプレートのすべてのインスタンス化を無効にするため、希望どおりにならない可能性があることに注意してくださいbool。たとえば、 は使用できませんfoo<int>。ただし、プライマリ テンプレートが未定義のままになっていることにも注意してください。このソリューションが要件に適合することを願っています。

于 2012-04-17T05:32:40.633 に答える
2

あなたが試みていることが可能だとは思いません。ここで同様の質問を見つけました。リンクはありませんが、c++ 標準の関連セクションは 14.8.2.5 です。以下は、テンプレート引数の推定に関するセクションからの引用です。

The non-deduced contexts are:
— The nested-name-specifier of a type that was specified using a qualified-id.
— A non-type template argument or an array bound in which a subexpression references a template
parameter.
— A template parameter used in the parameter type of a function parameter that has a default argument
that is being used in the call for which argument deduction is being done.
— A function parameter for which argument deduction cannot be done because the associated function
argument is a function, or a set of overloaded functions (13.4), and one or more of the following apply:
— more than one function matches the function parameter type (resulting in an ambiguous deduc-
tion), or
— no function matches the function parameter type, or
— the set of functions supplied as an argument contains one or more function templates.
— A function parameter for which the associated argument is an initializer list (8.5.4) but the parameter
does not have std::initializer_list or reference to possibly cv-qualified std::initializer_list
type. [ Example:
template<class T> void g(T);
g({1,2,3});
// error: no argument deduced for T
— end example ]
— A function parameter pack that does not occur at the end of the parameter-declaration-clause.

あなたの場合、修飾されたIDを使用してタイプを指定しているため、引数を推測できません。

あまり考えずに、簡単な回避策として、2 番目の型ではない bool パラメーターを foo に追加できます。次のようなものです。

template<typename T, bool is_decimal = false>
struct foo {...}; // general case

template<typename T>
struct foo<T, true> { ... }; // case where T is float or double

幸運を祈ります...

于 2012-04-17T05:29:01.627 に答える