3

私は正常に動作する次のコードを持っています:

list <Politician> MakeList ( int num, ... ){
  va_list arguments;                     
  va_start ( arguments, num ); 
  list <Politician> PoliticianList;
  for ( int x = 0; x < num; x++ ) {
      PoliticianList.push_back(va_arg (arguments, Politician));
  }
  va_end ( arguments );                 

  return PoliticianList;       
}

ただし、汎用にしようとすると、次のようになります。

template<class TYPE>
list <TYPE> MakeList ( int num, ... ){
  va_list arguments;                     
  va_start ( arguments, num ); 
  list <TYPE> PoliticianList;
  for ( int x = 0; x < num; x++ ) {
      PoliticianList.push_back(va_arg (arguments, TYPE));
  }
  va_end ( arguments );                 

  return PoliticianList;       
}

コンパイル時に次のエラーが発生します。

error C2783: 'std::list<TYPE> MakeList(int,...)' : could not deduce template argument for 'TYPE'

別のクラス オブジェクトに対して再実装する必要がないように、どうすればジェネリックにできますか?

4

1 に答える 1

3

TYPEテンプレート化されたバージョンの を呼び出すときは、 のテンプレート引数を明示的に指定する必要がありますMakeList。コンパイラは、指定した引数だけでは何TYPEが必要かを判断できないためです。たとえば、次の呼び出しがあるとします。

MakeList<Politician>(3, politician1, politician2, politician3)

コンパイラが何でTYPEあるかを推測する方法はありません。それが十分に賢いことを期待し、型のオブジェクトをPolitician引数として渡していると推測する場合、それはうまくいきません: C スタイルの可変引数関数は、コンパイル時にその情報を提供しません。

ただし、C++11 では、この目的のために可変個引数テンプレートを使用できます。これにより、特に最初の引数として後続の引数の数を渡さないようにすることができます。variadic を書き換える方法は次のMakeList()とおりです。

namespace detail
{
    template<typename T>
    void MakeList(std::list<typename std::remove_reference<T>::type>& l, T&& elem)
    {
        l.push_back(std::forward<T>(elem));
    }

    template<typename T, typename... Ts>
    void MakeList(
        std::list<typename std::remove_reference<T>::type>& l, 
        T&& elem, Ts&&... elems)
    {
        l.push_back(std::forward<T>(elem));
        MakeList(l, std::forward<Ts>(elems)...);
    }
}

template<typename T, typename... Ts>
std::list<typename std::remove_reference<T>::type> MakeList(
    T&& elem, Ts&&... elems)
{
    std::list<typename std::remove_reference<T>::type> l;
    detail::MakeList(l, std::forward<T>(elem), std::forward<Ts>(elems)...);
    return l;
}

その後、次のように使用できます。

int main()
{
    Politician p1{"John", "Smith"};
    Politician p2{"Mike", "Black"};
    Politician p3{"George", "White"};

    std::list<Politician> myList = MakeList(p1, p2, p3);

    for (auto const& p : myList)
    {
        std::cout << p.name << " " << p.surname << std::endl;
    }
}

これが実際のです。

于 2013-05-24T20:17:24.503 に答える