12

Debian スクイーズで gcc 4.4 を使用しています。次のコードを検討してください。

#include <map>
#include <string>
using std::map;
using std::string;

// Args lets the user specify additional explicit template arguments
template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
C<T, Args...> foo()
{
  C<T, Args...> x;
  return x;
}

int main(void)
{
  map<string, int> a = foo<string, map, int>();
}

したがって、ここでの考え方は、Tmatches stringCmatches map、およびテンプレート パラメーター パックのArgsmatchesintです。構文の一部が間違っている可能性があります。その場合は修正してください。特に、最初のテンプレート引数class Cを一致Tさせ、残りをテンプレート パラメータ pack と一致させたい場合、構文は正しいですかArgs?template <typename T, typename... Args> class C

これにより、エラーが発生します

In function 'int main()':
post.cc:18: error: no matching function for call to 'foo()'

これは、質問Variadic template templates and perfect forwardingに似ているようです。その質問は、これが gcc のバグであることを示唆していますが、これらの質問が同じことであると誤解している可能性があります。

優しくしてください。可変個引数テンプレートに関する私の知識は、12 時間も経っていません。重複を減らすために、いくつかの古い C++ コードを書き直そうとしていました。私がC++をやったのも久しぶりです。回避策がある場合は、お知らせください。ありがとう。

編集: Variadic テンプレート テンプレートのコメントで提案された回避策と、Ise Wisteriaによる完全な転送がうまくいきました。これは、これが同じバグであることを示唆しています。もちろん、私は今、(a) この回避策がどれほど壊れやすいか、(b) なぜ機能するのか、伊勢がそれを考えた動機は何なのか、疑問に思っています。伊勢しか答えられないんだろうけど。:-)

4

2 に答える 2

3

編集で説明したように、私の質問は、リンクされた質問、Variadic template templates および perfect forwarding と同じバグをくすぐるように見えます。特に、リンクに記載されている回避策は私の場合にも機能します。動作する変更されたコードは次のとおりです。

#include <map>
#include <string>
using std::map;
using std::string;

template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
struct X
{
  typedef C<T, Args...> type;
};

template <typename T,
      template <typename T, typename... Args> class C,
      typename... Args>
typename X<T, C, Args...>::type foo()
{
  C<T, Args...> x;
  return x;
}

int main(void)
{
  map<string, int> a = foo<string, map, int>();
}
于 2011-12-15T04:21:13.190 に答える
0

g++ 4.4 では、可変個引数のテンプレート パラメーターが非可変個引数と一致するとは思わないため、foo 関数を非可変個バージョンでオーバーロードする必要があります。

また、map には実際には 2 つ以上のテンプレート パラメーターがあるため、新しい foo 関数とも一致しないことに注意してください。

あなたの例へのこの追加はそれを明確にするはずです:

#include <map>
#include <string>
using std::map;
using std::string;

// Args lets the user specify additional explicit template arguments
template <typename T,
          template <typename T, typename... Args> class C,
          typename... Args>
C<T, Args...> foo() {
  C<T, Args...> x;
  return x;
}

template<typename T, template<typename, typename> class C, typename Arg>
C<T, Arg> foo() {
  return C<T, Arg>();
}

template<typename T, typename... Args> class A {};

template<typename T, typename Arg> class B {};

int main(void) {
  map<string, int> a = foo<string, map, int>(); // fails.
  A<string, int> x = foo<string, A, int>();
  B<string, int> y = foo<string, B, int>();
}
于 2011-12-15T03:32:32.223 に答える