ページ 1 / 1
C++のva_listとテンプレートの併用
Posted: 2011年11月18日(金) 15:58
by chibago
標題の通り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;
等として対応してみましたが上手くいきません。
何か良い方法はございませんでしょうか。
Re: C++のva_listとテンプレートの併用
Posted: 2011年11月18日(金) 16:11
by beatle
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();
}
Re: C++のva_listとテンプレートの併用
Posted: 2011年11月18日(金) 16:24
by beatle
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);
のようにしましょう。
Re: C++のva_listとテンプレートの併用
Posted: 2011年11月18日(金) 16:43
by たかぎ
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オプションが必要です。
Re: C++のva_listとテンプレートの併用
Posted: 2011年11月18日(金) 16:55
by beatle
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"));
}
Re: C++のva_listとテンプレートの併用
Posted: 2011年11月18日(金) 16:59
by chibago
betale様、たかぎ様、
ありがとうございました。
おかげさまで解決いたしました。
(ただcx0は少々抵抗がありますので、標準仕様になってから導入を検討いたしたいと思います。)
Re: C++のva_listとテンプレートの併用
Posted: 2011年11月18日(金) 17:10
by たかぎ
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();
}
というのでもよいでしょう。
Re: C++のva_listとテンプレートの併用
Posted: 2011年11月18日(金) 17:11
by たかぎ
chibago さんが書きました:(ただcx0は少々抵抗がありますので、標準仕様になってから導入を検討いたしたいと思います。)
すでにC++11は国際標準になっています。
Re: C++のva_listとテンプレートの併用
Posted: 2011年11月18日(金) 17:14
by beatle
chibago さんが書きました:(ただcx0は少々抵抗がありますので、標準仕様になってから導入を検討いたしたいと思います。)
ISOはもう通りましたので、既に標準仕様ですけれども。
参考:
http://www.open-std.org/jtc1/sc22/wg21/
追記
おうふ。たかぎさんともろかぶり!