C++のva_listとテンプレートの併用

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
chibago

C++のva_listとテンプレートの併用

#1

投稿記事 by chibago » 14年前

標題の通りC++(GCC)の可変引数に関してテンプレートが併用できなくて困っております。

コード:

template <typename T>
  void Test<T>::set_data(const int size, ...){
  va_list argptr;
  va_start (argptr, size);

  std::vector<T> result(size, 0.0);
  for (typename std::vector<T>::iterator  itr (result.begin());
                    itr!=result.end(); ++itr){
    *itr= va_arg (argptr, std::vector<T>::value_type);
  }   
  va_end (argptr);
  this->data = result;
}
このように、任意の数の入力を入れた際、この入力をvectorに格納して
メンバ変数に格納しようと考えております。このva_arg関数でテンプレート変数を
使うとコンパイル出来ないようです。(ここだけdoubleと指定すると上手くいきます。)

typedef std::vector<T> vector_T;

等として対応してみましたが上手くいきません。

何か良い方法はございませんでしょうか。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: C++のva_listとテンプレートの併用

#2

投稿記事 by beatle » 14年前

Visual C++ 2010 ほとんど無改造で動きましたよ。

コード:


#include <cstdarg>
#include <vector>
#include <iterator>
#include <iostream>
#include <algorithm>

template <typename T>
class Test
{
public:
	void set_data(const int size, ...);
	void print() const {
		std::copy(data.begin(), data.end(), std::ostream_iterator<T>(std::cout, "\n"));
	}
private:
	std::vector<T> data;
};

template <typename T>
void Test<T>::set_data(const int size, ...){
	va_list argptr;
	va_start (argptr, size);

	std::vector<T> result(size); // ここだけ変更。T型を0.0で初期化しようとしていた。
	for (typename std::vector<T>::iterator itr(result.begin());
		itr!=result.end(); ++itr){
			*itr= va_arg(argptr, std::vector<T>::value_type);
	}
	va_end (argptr);
	this->data = result;
}

int main()
{
	Test<int> t;
	t.set_data(3, 10, 20, 30);
	t.print();
}

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: C++のva_listとテンプレートの併用

#3

投稿記事 by beatle » 14年前

Ubuntuのg++でやってみました。確かにコンパイルエラーが出ますね。

コード:

test.cpp: メンバ関数 ‘void Test<T>::set_data(int, ...)’ 内:
test.cpp:27:10: エラー: expected type-specifier
test.cpp:27:10: エラー: ‘)’ が予期されます
test.cpp:27:10: エラー: ‘;’ が予期されます
これは、「std::vector<T>::value_type」が型名かどうか分からないから出ているエラーです。typenameを補って

コード:

            *itr= va_arg(argptr, typename std::vector<T>::value_type);
のようにしましょう。

たかぎ
記事: 328
登録日時: 15年前
住所: 大阪
連絡を取る:

Re: C++のva_listとテンプレートの併用

#4

投稿記事 by たかぎ » 14年前

GCCならそんな難しいことをしなくても、次のようにすればよいのでは?
(引数にsizeは不要ですよね?)

コード:

template <typename T>
class Test
{
public:
    void set_data()
    {
    }

    template <class U, class... Params>
    void set_data(U value, Params... params)
    {
        this->data.push_back(value);
        set_data(params...);
    }
private:
    std::vector<T> data;
};
こっちの方がシンプルですし、型安全ですし、TがPOD以外でも使えます。
強い例外安全保障のためにはもう一工夫いりますが、とりあえず上記でも機能は実現できるはずです。
なお、コンパイルするためには、-std=c++0xまたは-std=gnu++0xオプションが必要です。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: C++のva_listとテンプレートの併用

#5

投稿記事 by beatle » 14年前

C++11に走るならGCC 4.4からinitializer_listも使えますね。

コード:

#include <vector>
#include <initializer_list>
#include <iterator>
#include <iostream>
#include <algorithm>

template <typename T>
class Test
{
public:
    void set_data(std::initializer_list<T> init_list)
    {
        data_ = init_list;
    }
    const std::vector<T>& data() const
    {
        return data_;
    }
private:
    std::vector<T> data_;
};

int main()
{
    Test<int> t;
    t.set_data({10, 20, 30});
    std::copy(t.data().begin(), t.data().end(), std::ostream_iterator<int>(std::cout, "\n"));
}

chibago

Re: C++のva_listとテンプレートの併用

#6

投稿記事 by chibago » 14年前

betale様、たかぎ様、
ありがとうございました。

おかげさまで解決いたしました。
(ただcx0は少々抵抗がありますので、標準仕様になってから導入を検討いたしたいと思います。)

たかぎ
記事: 328
登録日時: 15年前
住所: 大阪
連絡を取る:

Re: C++のva_listとテンプレートの併用

#7

投稿記事 by たかぎ » 14年前

beatle さんが書きました:C++11に走るならGCC 4.4からinitializer_listも使えますね。
そうですね。シンタックスがかなり変わるので避けていました。

シンタックスが多少変わってもよいなら、C++11でなくても、GCC拡張を使って...

コード:

#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <cstddef>

template <typename T>
class Test
{
public:
    template <std::size_t N>
    void set_data(T const (&data)[N])
    {
        std::vector<T> temp(&data[0], &data[N]);
        this->data.swap(temp);
    }

    void dump()
    {
        std::copy(this->data.begin(), this->data.end(), std::ostream_iterator<T>(std::cout, "\n"));
    }
private:
    std::vector<T> data;
};

int main()
{
    Test<int> t;
    t.set_data((int[]){1, 2, 3});
    t.dump();
}
というのでもよいでしょう。

たかぎ
記事: 328
登録日時: 15年前
住所: 大阪
連絡を取る:

Re: C++のva_listとテンプレートの併用

#8

投稿記事 by たかぎ » 14年前

chibago さんが書きました:(ただcx0は少々抵抗がありますので、標準仕様になってから導入を検討いたしたいと思います。)
すでにC++11は国際標準になっています。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: C++のva_listとテンプレートの併用

#9

投稿記事 by beatle » 14年前

chibago さんが書きました:(ただcx0は少々抵抗がありますので、標準仕様になってから導入を検討いたしたいと思います。)
ISOはもう通りましたので、既に標準仕様ですけれども。
参考:http://www.open-std.org/jtc1/sc22/wg21/

追記
おうふ。たかぎさんともろかぶり!

閉鎖

“C言語何でも質問掲示板” へ戻る