【C++】template 統合スレ -- Part6
933 :
929:2005/09/14(水) 21:31:05
だからなんだよこのタコ助!
確かに余計だな。
935 :
929:2005/09/15(木) 00:04:09
>>933 >>929の著作権は私にあります。
なんなら出るとこ出ても・・
と思いましたがきっと
>>933は
私にインスパイヤされて誕生した新種なんでしょう。
今回はかんべんしてやります。
template <class T>
void f1(T t)
{
f2(t);
}
void f2(int) {}
int main()
{
f1(1);
}
というコードは正しいのでしょうか?
VC7.1 ではコンパイル可能で comeau ではコンパイルできません。
>>936 comeauだとなんてエラーが出るの?
938 :
636:2005/09/15(木) 13:09:16
>>637 identifier "f2" is undefined
detected during instantiation of "void f1(T) [with T=int]"
というエラーです。strict mode のみのようです。
ちなみに、ユーザ定義型の場合は期待通りにコンパイルできました。
template <class T>
void f1(T t)
{
f2(t);
}
struct a{};
void f2(a) {}
namespace adl
{
struct a{};
void f2(a) {}
}
int main()
{
f1(a());
f1(adl::a());
}
このコードはコンパイル成功。
>>936 gcc3.4.4(MinGW) で、-Wallで通る。
>>938 f2()のプロトタイプ宣言が必要っぽい。
Incompatibilities Between ISO C and ISO C++, David R. Tribble
http://david.tribble.com/text/cdiffs.htm#C90-impl-func ・ Implicit function declarations
> C++ does not allow implicit function declarations. It is invalid to call a function
> that does not have a previous declaration in scope.
>
> C99 no longer allows functions to be implicitly declared.
> The code above is invalid in both C99 and C++.
>>936 標準の (14.6.4.2/1) をそのまま読む限りでは, unqualified name lookup として
解決される名前は point of definition の文脈のみが考慮されて,
associated namespaces を用いた名前解決(要するにADL)では,point of definitionと
point of instantiation の双方の文脈が考慮されるみたいですね.なので,
>>936 の f1(1) という呼び出しにおける f1 中の f2(t) に対する名前解決の場合,
unqualified name lookup では f2 の呼び出しを定義している場所(point of definition)
からは f2 という名前は解決されないので失敗し,さらに f2(t) は int を引数とした
呼び出しのために associated sets of namespaces and classes も空 (3.4.2/2) の
ため,ADL 経由でも f2 は見つからずに,結果 f2(t) という関数呼び出しに対応する
名前の解決が失敗する.
一方で,
>>938 の f1(a()) 及び f1(adl::a()) という呼び出しにおける f1 中の f2(t)
に対する名前解決の場合,
>>936 と同様 unqualified name lookup による名前解決は
失敗する.ところが,a 及び adl::a はユーザ定義型で,各々グローバルと adl が
associated namespace になる.この場合,f2(t) という呼び出しが定義されている
場所 (point of definition) と f1 がインスタンス化された場所
(point of instantiation) 双方の文脈が名前解決において考慮される.結果,
point of instantiation の文脈で void f2(a) と void adl::f2(adl::a) が
visible のため,これらの名前解決が成功する.
と,こういう感じだと思います.ちなみに VC++7.1 の挙動は,dependent name だろうが
non-dependent name だろうが,ADL 経由だろうがなかろうが,全て
point of instantiation の文脈も考慮するという実装になっているための結果で,
これは標準に準拠した挙動ではないです.
944 :
943:2005/09/15(木) 17:49:27
あ,すいません.長々と書きましたけれど結論としては,
936のコードは(標準に準拠していないという意味で)正しくないと思います.
945 :
936:2005/09/15(木) 22:07:49
>>943 なるほど。
実体化の時点で名前の解決を行っても、
実体化の時点の文脈が考慮されるとは限らないんですね。
皆様、ありがとうございました。
template<class T>
class Foo {
public:
...;
private:
class Bar {
public:
...;
bool operator()(const Bar& l, const Bar&r) const;
private:
T m_value;
int misc_info;
};
std::multiset<Bar, Bar::Comp> m_bars;
};
m_bars の先頭・末尾に番人(misc_value などは他のメ
ンバと同様にアクセス可能にしたもの)を導入したいの
ですが、どういうアプローチで作れば良いでしょうか?
>>946 undeclared identifier `misc_value'
STLportではコンパイルできるけれど、
g++のSTLではエラーが出てしまうようなコードってどんなものがあるでしょうか?
vectorやstringくらいしか使ってないんですが、コンパイルでエラーが出ます。。
エラーメッセージ書かん奴には答えない
template<int num, int count> struct power{ enum { value = power<num, count-1>::value * num }; };
template<int num> struct power<num, 1>{ enum { value = num }; };
template<int num> struct power<num, 0>{ enum { value = 0 }; };
template<> struct power<0, 0>{ enum { value = 0 }; };
∋oノハヽo∈
( ´D`) <テンプレート ♪ で、計算♪計算♪ age♪ age♪
(つ┳9
(_)┃_)
━§━
§
⌒ヽ〃⌒ヽ〃
int main()
{ //2の8乗
cout << power<2, 8>::value << endl;
return 0;
}
>template<int num> struct power<num, 0>{ enum { value = 0 }; };
それはどうかと思うぞ。
template<int num> struct power<num, 0>{ enum { value = 1 };};
<0,0>,<num,1>の特殊化は必要ないな
むしろこうしてコンパイル時エラーにしろよ。
template<> struct power<0, 0>{};
0^0って数学的にはどうなるの?
スマン。レス番間違えた orz
>>957-958 一方で0 ^ n = 0となっているから問題になる。
ところで^と言えばXORの立場が。
VC6のtemplate関数ってバグある気がするんだけど...
template<typename T> void test();
引数無し呼んだときに解決できてないみたい...
template<typename T> void test(const T&);
みたいにすればオーバーロードで解決できるのか、大丈夫みたいなんだが...
いまどきそんな化石コンパイラに文句言われても…
化石以前にtemplateに関しては欠陥コンパイラですから・・・
そもそもC++コンパイラじゃないですから
少なくともANSI/ISO C++準拠とは言えないな。
じゃーVC7はどうですか?
7.1はかなりまとも。
7と7.1は全然違うぞ
7はかなり微妙
7はCStringにバグがあったね。STL周りもちょっと不安定なところがあった気もする。
7.1って具体的にclのどのバージョン?
今
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
っての使ってるけど
VS.net(VC.net)2003か、VCTK2003のやつが7.1
13.10.3077なら7.1だな。VS.net2003の方のやつだろ。
codeguruに記事の投稿してみたがレビュー通んないとだめなんだね
973 :
デフォルトの名無しさん:2005/10/18(火) 15:57:25
age
人稲杉なので、バカネタを投下。
http://www.hakusi.com/up/src/up5538.zip.html Boost.Lambda みたいに Expression Template を使った、引数に対して安全なフォーマットライブラリ。
Boost.Function や、Boost.Bind と組み合わせることが可能。
以前作成したものと違い、オマケ機能だが入力も可能で、ワイド文字にも対応。
ただ、 _ と % だらけで見た目がキモイ上に、実用性がイマイチ謎。
Expression Template の資料として。
// 出力
string strA, strB;
sprint( strA, "1 " % !_x[6] % "/" % _s, 10, "aaaa" ); // sprintf( str, "%#6x/%s", 10, "aaaa" ); みたいな。
sprint( strB, "2 " % (!_x[6]*='0') % "/" %_s, 10, "aaaa" ); // sprintf( str, "%#06x", 10, "aaaa" ); みたいな。
cout << strA << endl; // 1 0xa/aaaa と出力
cout << strB << endl; // 2 0x000a/aaaa と出力
// 入力
int xA, xB;
string yA, yB;
sscan( strA, "1 " % _ws % _x % "/" % _s, xA, yA ); // 空白部分はスキップさせる
sscan( strB, "2 " % _x % "/" % _s[3], xB, yB ); // 文字列部分は3文字のみ取得
// 出力
print( cout, "xA = " % _d % "\nyA = " % _s % _endl, xA, yA );
print( cout, "xB = " % _d % "\nyB = " % _s % _endl, xB, yB );
// xA = 10
// yA = aaaa
// xB = 10
// yB = aaa と出力
難読コンテスト会場はここですか?
977 :
デフォルトの名無しさん:2005/10/31(月) 13:08:43
>>974 すげー--w
確かに scanf っぽいこと出来るし。
でも、Perl みたいで汚いな。使おうとは思わんけど。
>>975 boostな人達はあれば便利だけど、一般人的にはどうなのかなあ?