マクソのVisual Studio .NETタダ版を取ってくればSTLのマニュアルが見られる(英語)
MSDNライブラリをダウンロードしたりオンラインで見たりとか。
あとは検索性が難だが、JIS X 3014がJISCのWebサイトから見れる。
939 :
デフォルトの名無しさん:2007/11/09(金) 22:56:01
なあ、下のクラスを-Wall -W -Weffc++でコンパイルすると、
なんかうるさい警告が山ほど出るけど、なんでだろ?
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/allocator.h:
In instantiation of `std::allocator<MyClass*>':
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_vector.h:79:
instantiated from `std::_Vector_base<MyClass*, std::allocator<MyClass*> >::_Vector_impl'
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_vector.h:110:
instantiated from `std::_Vector_base<MyClass*, std::allocator<MyClass*> >'
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_vector.h:142:
instantiated from `std::vector<MyClass*, std::allocator<MyClass*> >'
main.cpp:52:
instantiated from here
class MyClass {
public:
MyClass() {};
virtual ~MyClass() {};
};
vector<MyClass*> myvec;
int
main()
{
MyClass *p;
p = new MyClass();
myvec.push_back(p);
return 0;
}
940 :
デフォルトの名無しさん:2007/11/09(金) 23:18:00
スレチガイだったかもシレンが。。。
上記の警告を-Weffec++有効にしたままで抑制する方法ってあるんかな。
よくわからないけど、STLはEffectiveC++スタイルでコーディングされていないってことなんじゃないの?
942 :
912:2007/11/09(金) 23:53:17
>>915 >>907は確かに言葉が足りないと思うが、
安価先のレスを読めば意図を理解できるだろう。
それに比べて君は、君が馬鹿にしている
>>906より言葉が足りない。
もう少し、人のいわんとすることを理解しようとする努力と、
人に伝えるための努力が必要だろう。
まぁ、お前こそとっととチネがほんねだけれども。
>>940 システムヘッダファイルからは警告を出さない、っていうオプションがあったような気がする
945 :
デフォルトの名無しさん:2007/11/10(土) 19:41:45
#include <iostream>
template< int N >
class class1
{
public:
void print()
{
std::cout<<"test"<<std::endl;
}
};
template< int N >
class class2 :class1<N>
{
};
int main()
{
class2<42> obj;
obj.print(); //ここでコンパイルエラー
return 0;
}
'class1<42>::print()' はアクセスできないとコンパイラに怒られます。
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19 と似たようなエラーであることは分かったので、
obj.class1<42>::print();とか
(class1<42>)(&obj)->print();とか試してみましたが、やはり怒られます。
どう解決すればよいのか教えていただければ幸いです。
>>945 あなたが必要なのは
メンバ変数ですか?
それともテンプレートですか?
>>946 すみません、そうでした。
しばらくjavaしかやってなかったものですっかりpublic継承忘れてました。
>>947 一応テンプレートです。
void data_get(void** data);
こんなCの関数があって、これは俺が作ったものではないので変更できません。
typedef struct foo{
int a;
}foo;
こんな構造体があって、Cなら
foo *f;
data_get(&f);
こんな風に使います。
C++で今までVisual C++ 2005 で開発してこの関数を使うとき
foo* f;
data_get(reinterpret_cast<void**>(&f));
とやっていて、動作も特に問題が無かったのですが、g++4.1でコンパイルしたところ
warning: dereferencing type-punned pointer will break strict-aliasing rules
と怒られました。
一応この警告の意味とコードが標準に準拠してないことは理解したつもりですが
それでは、data_get関数をC++から安全に使うにはどのようにしたらいいでしょうか?
foo* f;
void** tmp = reinterpret_cast<void**>(&f);
data_get(tmp);
としてもも警告が出てしまいます。
void* tmp;
data_get(&tmp);
foo* f = reinterpret_cast<foo*>(tmp);
これだと警告が出ないのですが、大丈夫でしょうか。
>>949 void* tmp;
data_get(&tmp);
foo* f = static_cast<foo*>(tmp);
の方がいいんじゃない
>>949 reinterpret_cast は良くないね。最後のやつを static_cast に変えるのが最善かな。
>>949 C++なんだから、こっちで多重定義してしまえばいい。
inline foo_data_get(foo*& data)
{
void *p;
data_get(&p);
data = static_cast<foo*>(p);
}
953 :
949:2007/11/12(月) 00:32:02
ありがとうございます、
>>950か
>>952で行こうと思います。
ところで、void*からのキャストはreinterpret_castもstatic_castも同じだと思ってたんですが
違うんですか?
>>953 reinterpret_cast は実装依存。 static_cast は foo* → void* への暗黙の変換の逆変換。
どっちも同じになる実装がほとんどだろうけどね。
暗黙の変換を明示的に行うのがstatic_castだってeffective C++に書いてあった
>>955 それだけではないけどね
void* -> T* の暗黙の変換はないけど
これもstatic_castの仕事の一つ
test.cxxというファイル名だと、
__FILE__がtest.cxxになりますが、
#define test.cxx
と同等のことを__FILE__を使ってできませんか?
>>957 識別氏にピリオドを含むことはできません。定義するマクロ名にマクロ展開の結果は使えません。
959 :
デフォルトの名無しさん:2007/11/12(月) 22:55:33
>>949 g++ -fno-strict-aliasing じゃだめ?
>>949 C++もCと同じだと思うけど、
汎用(void)のポインタへのポインタ型というのは規格上ないはず。
void func(void **);
int *p;
func((void **)&p);
こういうコードは移植性がなく動作は未定義。
正しくは、
void *vp = p;
f(&vp);
p = vp;
なので自分で書いてるとおりvoidポインタを介在させればよい。
foo *f;
void *tmp = f;
data_get(&tmp);
f = static_cast<foo*>(tmp);
でいいんでは?
>>960 void**という型がないわけではない。
ただ、T**――Tはvoid以外の任意の型(あー、一応関数型も除く)――
とvoid**との間の変換が定義されていないだけ。
962 :
デフォルトの名無しさん:2007/11/13(火) 03:39:21
グローバル変数の定義順序について質問させてください。
--- values.cpp ---
int values[] = { 5, 1, 2, 4, ... };
--- values.h ---
extern int values[];
--- table.cpp ---
#include "values.h"
int table[] = { values[0], values[1], values[2], ... };
こんな風に、異なる翻訳単位に2つのグローバル変数
values[] と table[] があって、table[] の初期化が values[] に
依存しているときに、コンパイラはこの依存関係(?)をちゃんと
検出してグローバル変数の定義順序を決めてくれるもんなんでしょうか?
詳しい方おられましたら、よろしくお願いします。
定義した順に初期化される。
table.cppは int table[]... の前に extern int values[]; を展開する。
964 :
962:2007/11/13(火) 03:44:24
すみません、このサンプルで御願いします…。
--- values.cpp ---
int values[] = { 5, 1, 2, 4, ... };
int get_value(int i) { return values[i]; }
--- values.h ---
int get_value(int);
--- table.cpp ---
#include "values.h"
int table[] = { get_values(0), get_values(1), get_value(2), ... };
x定義した順に初期化される。
o宣言した順に
自分でコンパイルしろよカス
967 :
デフォルトの名無しさん:2007/11/13(火) 03:59:33
宣言した順ということは、どちらの翻訳単位が先に翻訳されるか
によって変わるということでしょうか。
手元のコンパイラ BorlandC++BuilderX でどちらも試してみましたが、
警告もエラーもなく期待通りに初期化されるようなので、良く分かりません。
table[] の初期化が values[] の初期化より先に行われるようなコンパイラが
あるとすれば、問題が起こるかもと思ったのですが。
>>964 その場合 values は定数式で初期化されているので静的初期化になります。
table は定数式じゃないので動的初期化になります。非ローカルオブジェクトの
初期化は静的初期化が先で動的初期化が後なので、その例だと問題は起こり
ません。
静的初期化には特に順番というものがありません。動的初期化については
同じ翻訳単位内での順番は定義順と決まっていますが、翻訳単位をまたぐと
順番が定まらなくなりますので、その場合に問題が起こる可能性があります。
969 :
949:2007/11/13(火) 08:20:18
>>959 それやったら負けかなと思ってる。
「最適化しても良い」って決まりですし。
>>960-961 ふむふむ、
そういえなvoid**はvoid*とは違って全然汎用ではないですね
>>969 そりゃそうだ、void **はvoid *へのポインタに過ぎない。
>>966 実行速度を計測するのと違って、自分の環境でたまたまうまくいけば
それで疑問が晴れる、というものではないから、それは見当違いの反応だよ。
>>961 >>969 汎用(void)はおかしかった。void**がないわけではなく
”汎用として使えるポインタへのポインタ型はない”
と言いたかった。ここでいう汎用とはあるT型から
の変換とT型への変換ができるということ。
(不完全型へのポインタなので変換できない)
詳しくはCプログラミングFAQ
973 :
デフォルトの名無しさん:2007/11/13(火) 10:25:43
教えてください。
void *vp;
があったとして
*vpのようにデリファレンスすることはできませんが
void** vpp;
があったとして、これを*vppのようにデリファレンスするのはOK
ですよね?(*vppはただのポインタで結果はvoid*となるので)
974 :
973:2007/11/13(火) 10:27:03
訂正
(*vppはただのポインタで結果はvoid*となるので) ×
(vppはただのポインタで*vppの結果はvoid*となるので) ○
975 :
973:2007/11/13(火) 10:40:19
念のため確認させて欲しいのですが
void MyMemoryAlloc(void **vpp, size_t n)
{
.
. 詳細は省略
.
*vpp = malloc(n * sizeof(T)); //確保したメモリへのポインタ
}
T *p;
void *vp = p;
MyMemoryAlloc(&vp, 10);
p = vp;
というのはOKですよね?というかよくありますよね?
>>973 おk
だけど
>>975 T *p;
MyMemoryAlloc(&p, 10);
これでよくね?
ただし、TがPOD型のみ有効。
is_podは現行のC++ではあまり使えないらしいし怖いのぅ
978 :
973:2007/11/13(火) 11:45:20
>>976 ご説明ありがとうございます。
T *p;
MyMemoryAlloc(&p, 10);
としてしまうと、
>>961さんご指摘のように
T** から void**への暗黙の変換が
できないですよね?
(POD型というのが分からなかったのですが。)
>>968 ありがとうございます。勉強になりました。
>>962のサンプルの場合も、table[] の初期化子 (values[0] など)は
定数式ではない(配列の要素は const であっても定数式にならないん
でしたよね) ので、やはり values が table より先に(静的)初期化される、
と考えて良いんですね。
>>978 あまり深く考えずに、
template<typename T> T * vp_assign( T * & lhs, void * rhs){
return lhs = static_cast<T *>(rhs);
}
template<typename T> T * vpp_assign( T ** lhs, void ** rhs) {
return vp_assign(*lhs, *rhs);
}
とか作って、それを使えばいいじゃまいか
982 :
981:2007/11/14(水) 02:37:59
盛大にアンカーミスった。 379 じゃなくて
>>979 ね。
>>975 p = vp はコンパイルできない。 static_cast が必要。
>>976 void** の引数に T** は渡せない。
>>980 意味が分からないから、たぶんやめたほうがいい。