5ちゃんねる ★スマホ版★ ■掲示板に戻る■ 全部 1- 最新50  

■ このスレッドは過去ログ倉庫に格納されています

【C++】template 統合スレ -- STL/Boost/Loki, etc.

1 :デフォルトの名無しさん:02/11/20 21:29
C++ のジェネリックプログラミングの話をしましょう。
以下のスレッドを統合するスレです。

STLスレッド
Part1 http://pc.2ch.net/tech/kako/1004/10042/1004287394.html
Part2 http://pc3.2ch.net/test/read.cgi/tech/1026793823/

【C++】Boost使い集まれ!
http://pc3.2ch.net/test/read.cgi/tech/1033830935/

Generic Programming with C++ Template
http://pc.2ch.net/tech/kako/1008/10085/1008593126.html

関連スレ、その他リンクは >>2-5 あたりに。

614 :デフォルトの名無しさん:03/01/26 16:06
>>610
その場合、mySetのデストラクタにvirtualが要る。

MultiSetの実装が謎だ。なんでコンパイルとおるんだ?
絶対解決してないと思うんだが?

615 :デフォルトの名無しさん:03/01/26 16:10
>>611
vector<T>::iterator が T* という良くある環境だと問題ないけど、STLport の
デバッグモードみたいに別の型が返ってくる(それをデリファレンスすると T
になる)だと、怒られそうな気がする。

とはいえ微妙に使いにくい仕様だな、これ。>>609 にあるような C 言語の関
数を呼ぶ場合、どうせ C 関数の方で要素数チェックして 0 なら何もしない、
ってのが普通だし、そっちにチェックを任せたいよな。

616 :611:03/01/26 16:11
ニヤリ

617 :デフォルトの名無しさん:03/01/26 16:12
610です
このようにしましたけど、問題ないようです。
環境はBCB5でWindowsXPです。

//重複なしのコンテナ
class UniqueSet : public mySet {
std::set<AnsiString> container_;
std::set<AnsiString>::iterator itrator_;
public:
void insert(AnsiString& s) { container_.insert(s); }
unsigned int getSize(void){ return container_.size(); }
iterator begin(void){ return container_.begin(); }
iterator end(void){ return container_.end(); }
};
//重複ありのコンテナ
class MultiSet : public mySet {
std::multiset<AnsiString> container_;
std::multiset<AnsiString>::iterator itrator_;
public:
void insert(AnsiString& s) { container_.insert(s); }
unsigned int getSize(void){ return container_.size(); }
iterator begin(void){ return container_.begin(); }
iterator end(void){ return container_.end(); }
};

618 :デフォルトの名無しさん:03/01/26 16:21
std::set<int>::iterator f() { return std::multiset<int>::iterator(); }

gccでも↑のコードがエラーにならん。
仕様じゃ、ないよな?

619 :デフォルトの名無しさん:03/01/26 16:25
>>615
size()==0よりもempty()を使えって話になるんじゃないか?

620 :デフォルトの名無しさん:03/01/26 16:36
>>619
それでも

extern "C" void foo(int *data, size_t num);

に対して、これを利用する C++ 側関数は

vector<int> v;
if (!v.empty())
  foo(&v[0], v.size());

と場合分けが必要になるよね。

621 :デフォルトの名無しさん:03/01/26 16:47
>>620
↓で問題ないと思う。

inline
void foo( vector<int>& v )
{
  if(!v.empty())
    foo(&v[0],v.size());
}


622 :デフォルトの名無しさん:03/01/26 17:34
>>621
俺だったらこんな関数作って使うかな。

templat<class T>
inline T* GetFirstPointer( vector<T>& v )
{
 if(v.empty())
  return NULL;
 else
  return &v[0];
}

で、vectorが空でも&v[0]が許される実装で、
かつ効率が気になる場合は
単純に&v[0]を返すように書き換えると。

623 :622:03/01/26 17:37

誤:templat<class T>
正:template<class T>

624 :デフォルトの名無しさん:03/01/26 17:45
>>622
>621のコードを見てなお、>622のコードを使いたくなるのって、どんなとき?

625 :デフォルトの名無しさん:03/01/26 18:06
悲しいときー

626 :デフォルトの名無しさん:03/01/26 18:35
>>624
ラッパ関数を沢山書くのが面倒な場合だろう。

627 :622:03/01/26 18:35
>>624
fooに相当する関数が沢山あるとき。

628 :622:03/01/26 18:54
カブった....。

あとfooが関数オブジェクトだった時や、
fooがvectorのサイズを変更しないことを示したい時にも
>622の方を使いたくなるな。

629 :デフォルトの名無しさん:03/01/26 18:55
>>627
ということは、末端のコードにGetFirstPointerがばら撒かれるわけか。
  foo(GetFirstPointer(v),v.size());
・・・うーん、あんまり賛成できないなぁ。

630 :629:03/01/26 19:02
>>628
> fooがvectorのサイズを変更しないことを示したい時にも

あー、それあるなぁ。
やっぱりしょうがないかぁ。

631 :デフォルトの名無しさん:03/01/26 19:10
>>629
いっそ vector 継承して operator[] だけ再定義したオブジェクトを作るのも
手かもしれんな。

メンバ変数は一切増えないから、デストラクタが virtual でなくとも支障ない
しさ。

632 :629:03/01/26 19:43
>>631
そりゃあんまりだ。

633 :デフォルトの名無しさん:03/01/26 20:10
>>611-612
でもさ、vector::operator[] って reference を返すじゃん。
てことは、&v[0] は dereference を実行してないと思うんだけど。

まあでも、v.size() == 0 の場合、要素配列を格納するための
有効なバッファがが確保されているかどうかは不明だしねぇ。
やっぱり v.empty() で切り分けるしかないかなぁ。

634 :デフォルトの名無しさん:03/01/26 20:26
>>633
> でもさ、vector::operator[] って reference を返すじゃん。
で、規格書読むと reference は「有効なオブジェクトを指さねばならない」と書いてあったり
するわけだ。

> てことは、&v[0] は dereference を実行してないと思うんだけど。
これは &(*v.begin()) と同じ意味なんだが、v.begin() が返すのが単なるポインタではない
場合には、実際に dereference が行われた上で、そのアドレスが計算されることになる。
たいていの処理系だと vector<T>::iterator は T* だから問題ないけど。

635 :601:03/01/26 21:58
>>592
やはり別の理由でした。自作スマートポインタが、変な形式の operator new を持っていたのがいけなかったようです。
(g++ に切り替えてわかったのですが、boost::mem_fn ではなくて、その前のコンテナに突っ込むところでのエラーだったようです。)
それを取り除いて、自作ポインタ用の get_pointer を追加した所、うまくいきました。

ありがとうございました。

636 :635:03/01/26 22:34
それと気がついた事を一つ。

get_pointer は koenig look-up があるので 名前空間 boost に入れなくても
よさそうです。

637 :592:03/01/26 23:34
>>636
VC6って演算子じゃない関数は Koenig Lookup 出来ないんじゃなかったっけ。
最近使ってないからはっきり覚えてはいないけど…。

638 :デフォルトの名無しさん:03/01/26 23:52
昔、数値計算用に3次元や2次元ベクトルクラス(double型のみ)を自作したりしたんだけど、
最近になってテンプレート化してみたら、同じ型同士は問題なく動くけど
違う型を混ぜると下のように怒られちゃいました。
型をあわせなきゃいけないみたいだけどどうすればいいのでしょう……


borland c++ 5.5でつ

vec3<double> a
vec3< complex<double> > b,c

c=a*b;

『エラー E2094 : * 演算子が使われたがクラス Vec3<complex<double >> では Vec3<double> 型のための定義が存在しない』

639 :デフォルトの名無しさん:03/01/27 00:05
vec3<double> + vec3< complex<double> > で、あなたの書いたどのコードが
実行されると期待しているんだ?

640 :デフォルトの名無しさん:03/01/27 00:13
>>638
本質的には T から U への型変換が存在する時に、vec<T> から vec<U> への
型変換を認めたい、って話だよね。

それなら、テンプレート化したコピーコンストラクタを作る。vec3 の実装がどうなっ
てるか知らんけど、かりに vec3<T> が private 変数として T 型の配列 v_[3] を
持つと仮定すると、

template <typename T>
class vec3
{
public:
  template <typeename U>
  vec3(const vec3<U>& other)
    : v_(other.v_)
  {}
};

ってな感じ。other.v_ (U[3]型) から v_ (T[3] 型) への暗黙の型変換がある場合、
これでよろしく変換できる。

641 :デフォルトの名無しさん:03/01/27 00:55
ありがとう。何を調べればよいのかが解らないと自分一人ではどうにもならんので。

配列だと余分なアクセス入るかなと思って、ベクトルの各成分はT v[3]じゃなくてT x,y,zで実装してます。
もっと次数が高ければ当然配列にするだろうけど……あ、配列だったらSTLのvector使えばいいのか。

明日試してみます

642 :デフォルトの名無しさん:03/01/27 01:26
テンプレートクラスをstd::ostreamに出力するにはどのように定義すれば
いいのでしょうか?
コンパイルできるのですがワーニングが出ます。gcc3.2.1(MinGW)です。

template <typename T>
class A {
T value;
public:
A(double d = 0) {
value = d;
}
friend std::ostream& operator<<(std::ostream& os, const A<T>& a);
};

std::ostream& operator<<(std::ostream& os, const A<double>& a)
{
os << a.value;
return os;
}

int main()
{
A<double> a(1.23);
std::cout << a << std::endl;
}

643 :デフォルトの名無しさん:03/01/27 01:30
>>642
なんでそのコンパイラの出力をはぶきやがるんだ?

644 :デフォルトの名無しさん:03/01/27 01:37
>>643
すみません、ワーニングをコピペします。

g++.exe "C:\MinGW\Learn\Learn2\template_ostream.cpp" -o "C:\MinGW\Learn\Learn2\template_ostream.exe" -Wall -s -O3 -I"C:\mingw\include" -I"C:\mingw\include\c++" -I"C:\mingw\include" -L"C:\mingw\lib"
C:/MinGW/Learn/Learn2/template_ostream.cpp:10: warning: friend declaration `
std::ostream& operator<<(std::ostream&, const A<T>&)' declares a
non-template function
C:/MinGW/Learn/Learn2/template_ostream.cpp:10: warning: (if this is not what
you intended, make sure the function template has already been declared and
add <> after the function name here) -Wno-non-template-friend disables this
warning

Execution terminated
Compilation successful

645 :デフォルトの名無しさん:03/01/27 01:47
>>644
Friend declaration `std::ostream& operator<<(std::ostream&, const A<T>&)'
declares a non-template function.
If this is not what you intended, make sure the function template has
already been declared and add <> after the function name here.
-Wno-non-template-friend disables this warning.

・・・ってなワケだ。あとは好きなように対処しな。

646 :デフォルトの名無しさん:03/01/27 01:58
>>645
次のようにしたらコンパイル通りました。ありがとうございました。
ちなみにBCC5.6では通りませんね。

template <typename T>
class A {
T value;
public:
A(double d = 0) {
value = d;
}
friend std::ostream& operator<< <>(std::ostream& os, const A<T>& a);
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const A<T>& a)
{
os << a.value;
return os;
}

int main()
{
A<double> a(1.23);
std::cout << a << std::endl;
}

647 :636:03/01/27 16:44
>>637
なはは…うっかり忘れてました。
その間についに VC++ に別れを告げる決意を固めて、試したのは g++ 上でした。

VC++ では通らないかもしれないです。

648 :638:03/01/28 01:03
>640
無事complex<double> とdouble間の計算が出来ますた。有難う

649 :デフォルトの名無しさん:03/01/28 03:11
テンプレート引数の型を文字列リテラルとして取り出したいんですが
どうすればいいでしょう。つまりログとりたいんです

template<typename T>
class Hoge {
public:
 Hoge() {
  Log::debug("Hoge<T>::Hoge()");
 }
};

Hoge<int> hoge;

で Hoge<int>::Hoge() と表示してほしいんですが・・・

650 :デフォルトの名無しさん:03/01/28 03:22
>>649
typeid(T).name()

651 :デフォルトの名無しさん:03/01/28 03:24
>>649
typeid(T).name()

652 :651:03/01/28 03:25
>>650
ケコーン

653 :デフォルトの名無しさん:03/01/28 03:27
それはconst char*でして、文字列リテラルではないかと・・・
コンパイル時に Hoge<int>::Hoge になって欲しいんです・・・

654 :デフォルトの名無しさん:03/01/28 03:36
>>653
無理。
std::string でも使え。

655 :デフォルトの名無しさん:03/01/28 03:50
ガビーン
あきらめます・・・

656 : :03/01/28 17:55

"<" と ">" に挟まれた文字列を検索して格納したいのですが。
これで良いでしょうか?

{
    std::string text;
    std::string __text;
    std::string::iterator i_first;
    std::string::iterator i_last;

    i_first = __text.begin() + __text.find( "<", 0 ) + 1;
    i_last = __text.begin() + __text.find( ">", 0 );

    text.assign( i_first, i_last );
}


657 :デフォルトの名無しさん:03/01/28 18:31
>>656
例えばこんなのはどうか。

std::string text;
std::string __text;
std::string::iterator i_first;
std::string::size_type st;

i_first = __text.begin() + __text.find("<") + 1;
st = __text.find(">") - __text.find("<") - 1;

text.assign(i_first, st);

658 :デフォルトの名無しさん:03/01/28 18:41
これでもいい。
std::stringはイテレータよりもインデックスで扱った方が
扱いやすいようだ。

std::string text;
std::string __text("aaa<abc>def");
std::string::size_type st, st2;

st = __text.find("<") + 1;
st2 = __text.find(">") - __text.find("<") - 1;

text = __text.substr(st, st2);

659 :デフォルトの名無しさん:03/01/28 18:57
文字列が"abd>efg<hijklmn"とかだと破綻しねぇか? 全部。

660 :デフォルトの名無しさん:03/01/28 18:59
>>659
エラーチェックしてないから。したらしたなりになる。

661 :デフォルトの名無しさん:03/01/28 20:21
>>656
boost::regex使えばいいのに。

662 :656:03/01/28 20:36
正規表現で探すのは後に実装する予定でした。
とりあえず抽出だけを考えてます
それで、関数を作ってみました。

const std::string Extraction
(
const std::string text,
const std::string text_open,
const std::string text_close
)
{
std::string output = "";
std::string::size_type position_open = 0;
std::string::size_type position_close = 0;
std::string::size_type position_target = 0;

position_open = text.find( text_open, 0 );
if( position_open == std::string::npos ) return ( const std::string )"";

position_close = text.find( text_close, position_open );
if( position_close == std::string::npos ) return ( const std::string )"";

position_target = position_open + text_open.length();

output.assign( text, position_target, position_close - position_target );

return ( const std::string )output;
}


663 :656:03/01/28 20:37
使用してみました

std::string t;
t = Extraction( "a<b<c<d", "<", ">" ); // 無
t = Extraction( "a<b<c>d", "<", ">" ); // b<c
t = Extraction( "a<b>c<d", "<", ">" ); // b
t = Extraction( "a<b>c>d", "<", ">" ); // b
t = Extraction( "a>b<c<d", "<", ">" ); // 無
t = Extraction( "a>b<c>d", "<", ">" ); // c
t = Extraction( "a>b>c<d", "<", ">" ); // 無
t = Extraction( "a>b>c>d", "<", ">" ); // 無

STL 初心者なもので、色々と不具合があるかもしれません。
みなさんどうもありがとうございました

217 KB
■ このスレッドは過去ログ倉庫に格納されています

★スマホ版★ 掲示板に戻る 全部 前100 次100 最新50

read.cgi ver 05.04.02 2018/11/22 Walang Kapalit ★
FOX ★ DSO(Dynamic Shared Object)