42

次のコード:

template <typename S, typename T>
struct foo {
   void bar();
};

template <typename T>
void foo <int, T>::bar() {
}

エラーが表示されます

invalid use of incomplete type 'struct foo<int, T>'
declaration of 'struct foo<int, T>'

(私は gcc を使用しています。) 部分的な特殊化の構文は間違っていますか? 2 番目の引数を削除すると、次のようになることに注意してください。

template <typename S>
struct foo {
   void bar();
};

template <>
void foo <int>::bar() {
}

その後、正しくコンパイルされます。

4

5 に答える 5

46

関数を部分的に特殊化することはできません。メンバー関数でこれを行いたい場合は、テンプレート全体を部分的に特殊化する必要があります (はい、イライラします)。大規模なテンプレート クラスで関数を部分的に特殊化するには、回避策が必要です。おそらく、テンプレート化されたメンバー構造体 (例: template <typename U = T> struct Nested) が機能するでしょう。または、部分的に特殊化された別のテンプレートから派生させることもできます (this->member表記法を使用すると機能しますが、そうしないとコンパイル エラーが発生します)。

于 2008-10-03T00:05:53.807 に答える
8

copro はすでに 2 つの解決策について言及し、Anonymous は 2 つ目の解決策を説明しましたが、最初の解決策を理解するのにかなりの時間がかかりました。おそらく、次のコードは、私のように、まだグーグルで上位にランクされているこのサイトに出くわした人にとって役立つでしょう. 例 (numericT のベクトル/配列/単一要素を dataT として渡し、[] を介して、または直接アクセスする) はもちろんいくらか工夫されていますが、メンバー関数をラップすることで部分的に特殊化することに実際にどのように近づくことができるかを示す必要があります。部分的に専門化されたクラスで。

/* The following circumvents the impossible partial specialization of 
a member function 
actualClass<dataT,numericalT,1>::access
as well as the non-nonsensical full specialisation of the possibly
very big actualClass. */

//helper:
template <typename dataT, typename numericalT, unsigned int dataDim>
class specialised{
public:
  numericalT& access(dataT& x, const unsigned int index){return x[index];}
};

//partial specialisation:
template <typename dataT, typename numericalT>
class specialised<dataT,numericalT,1>{
public:
  numericalT& access(dataT& x, const unsigned int index){return x;}
};

//your actual class:
template <typename dataT, typename numericalT, unsigned int dataDim>
class actualClass{
private:
  dataT x;
  specialised<dataT,numericalT,dataDim> accessor;
public:
  //... for(int i=0;i<dataDim;++i) ...accessor.access(x,i) ...
};
于 2014-05-19T13:05:11.567 に答える
5

コンストラクターを部分的に特殊化する必要がある場合は、次のようなものを試すことができます。

template <class T, int N>
struct thingBase
{
    //Data members and other stuff.
};

template <class T, int N> struct thing : thingBase<T, N> {};

template <class T> struct thing<T, 42> : thingBase<T, 42>
{
    thing(T * param1, wchar_t * param2)
    {
        //Special construction if N equals 42.
    }
};

注: これは、私が取り組んでいるものから匿名化されたものです。これは、非常に多くのメンバーを持つテンプレート クラスがあり、関数を追加するだけの場合にも使用できます。

于 2011-06-04T19:06:55.423 に答える
1

C++ 17 では、"if constexpr" を使用して、メソッドの特殊化 (および書き換え) を回避しています。例えば ​​:

template <size_t TSize>
struct A
{
    void recursiveMethod();
};

template <size_t TSize>
void A<TSize>::recursiveMethod()
{
    if constexpr (TSize == 1)
    {
        //[...] imple without subA
    }
    else
    {
        A<TSize - 1> subA;

        //[...] imple
    }
}

A<1>::recursiveMethod() を特殊化することを避けます。このメソッドは、次の例のような型にも使用できます。

template <typename T>
struct A
{
    void foo();
};

template <typename T>
void A<T>::foo()
{
    if constexpr (std::is_arithmetic_v<T>)
    {
        std::cout << "arithmetic" << std::endl;
    }
    else
    {
        std::cout << "other" << std::endl;
    }
}


int main()
{
    A<char*> a;
    a.foo();

    A<int> b;

    b.foo();
}

出力:

other
arithmetic
于 2020-08-22T19:03:56.553 に答える