web-dev-qa-db-ja.com

部分的なテンプレートの特殊化による「不完全な型の無効な使用」エラー

次のコード:

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() {
}

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

35
Jesse Beder

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

38
coppro

Copproはすでに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) ...
};
7
Echsecutor

コンストラクターを部分的に特殊化する必要がある場合は、次のようなことを試してみてください。

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.
    }
};

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

3