6

g++次のコードで 3.3から奇妙なエラーが発生します。

#include <bitset>
#include <string>

using namespace std;

template <int N, int M>
bitset<N> slice_bitset(const bitset<M> &original, size_t start) {
    string str = original.to_string<char, char_traits<char>, allocator<char> >();
    string newstr = str.substr(start, N);
    return bitset<N>(newstr);
}

int main() {
    bitset<128> test;
    bitset<12> result = slice_bitset<12, 128>(test, 0);
    return 0;
}

エラーは次のとおりです。

関数 `std::bitset slice_bitset(const std::bitset&, unsigned int)':
`,' トークンの前の構文エラー
declarator-id として指定された「char_traits」
`char_traits' の宣言で 2 つ以上のデータ型
declarator-id として指定された「allocator」
「アロケータ」の宣言で 2 つ以上のデータ型
`>' トークンの前の構文エラー

それは本当にばかげたことに違いありませんが、私はすでにゴム製のアヒルと友人にそれを伝えましたが、役に立ちませんでした.

ありがとう、レイジーウェブ。

4

3 に答える 3

10

上記のCAdakerから選択された回答は問題を解決しますが、問題を解決する理由は説明していません。

関数テンプレートが解析されている場合、依存型ではルックアップは行われません。その結果、次のような構造を解析できます。

template <typename T>
class B;

template <typename T>
void foo (B<T> & b) {
  // Use 'b' here, even though 'B' not defined
}

template <typename T>
class B
{
  // Define 'B' here.
};

ただし、この「機能」にはコストがかかります。この場合、「foo」の定義には、テンプレート「B」の内容に関するヒントが必要です。'foo' が 'B' のネストされた型を使用する場合typename、名前が型であることをコンパイラに伝えるためにキーワードが必要です。

template <typename T>
void foo (B<T> & b)
{
  typename B<T>::X t1;    // 'X' is a type - this declares t1
  B<T>::Y * t1;           // 'Y' is an object - this is multiplication
}

上記の 'typename' がない場合、コンパイラはそれXがオブジェクト (または関数) であると想定します。

<同様に、メンバー関数が呼び出され、その呼び出しに明示的なテンプレート引数がある場合、コンパイラは、を小なり演算子ではなく、テンプレート引数リストの開始として扱う必要があります。

template <typename T>
void foo (B<T> & b)
{
  b.template bar<int> (0); // 'bar' is a template, '<' is start of arg list
  b.Y < 10;                // 'Y' is an object, '<' is less than operator
}

がないtemplate場合、コンパイラはそれ<がより小さい演算子であると想定し、それint>が式ではないことを確認すると構文エラーを生成します。

これらのヒントは、テンプレートの定義が表示されている場合でも必要です。その理由は、明示的な特殊化によって、実際に選択された定義が後で変更される可能性があるためです。

template <typename T>
class B
{
  template <typename S>
  void a();
};

template <typename T>
void foo (B<T> & b)
{
  b.a < 10;            // 'B<int>::a' is a member object
}

template <>
class B<int>
{
  int a;
};
于 2008-10-27T11:53:42.117 に答える
7

どちらかだけを使用してください

original.to_string();

または、型指定子が本当に必要な場合は、

original.template to_string<char, char_traits<char>, allocator<char> >();
于 2008-10-23T23:12:09.773 に答える
2

以下は私のためにコンパイルされました(gcc 3.4.4を使用):

#include <bitset>
#include <string>

using namespace std;

template <int N, int M> 
bitset<N> slice_bitset(const bitset<M> &original, size_t start) 
{   
  string str = original.to_string();
  string newstr = str.substr(start, N);    
  return bitset<N>(newstr);
}

int main() 
{ 
  return 0; 
}
于 2008-10-23T23:20:12.533 に答える