[表示 : 全て 最新50 1-99 101- 201- 301- 2chのread.cgiへ]
Update time : 05/10 09:44 / Filesize : 95 KB / Number-of Response : 338
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

C++相談室 part60



1 名前:デフォルトの名無しさん mailto:sage [2008/01/11(金) 18:43:34 ]
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレに
お願いします。

145 名前:139 mailto:sage [2008/01/25(金) 13:54:25 ]
あと,実際には>>141さんが指摘しているように
名前が付いた右辺値参照は左辺値として扱われるので,
右辺値として渡された f の引数を f の内部で引き続き右辺値として扱うには
明示的に右辺値参照に変換してやらないといけないです.
で,このために std::forward という補助的な関数テンプレートも提案されています.

template<typename T>
T &&forward(typename identity<T>::type &&x){return x;}

template<typename T>
void f(T &&x)
{
  g(forward<T>(x)); // f が右辺値で呼ばれている場合, T が非参照型になっているので
                         // forward の戻り値型が右辺値参照型になり,右辺値として g に渡される.
                         // f が左辺値で呼ばれている場合, T が参照型になっているので
                         // forward の戻り値型が左辺値参照型になり,左辺値として g に渡される.
}

146 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 15:50:00 ]
>>143
boost::refについて、これ嘘だった。


147 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 16:25:54 ]
まったく話についてけないんだが。
何が左辺値で何が右辺値なんだかもうわけわからん
右辺値で呼ぶってどういうこと?

148 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 16:44:11 ]
template <class T>
struct identity
{
typedef T type;
};

template <class T>
inline
T&&
forward(typename identity<T>::type&& t)
{
return t;
}


149 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 16:49:21 ]
>>144
f(i); // T = int & として f が specialization される.

T が int & にdeductionされるのって、パラメータが右辺値参照
のときのみのルールですよね?

150 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 16:52:33 ]
Let us first consider the rvalue reference type, T &&, in more detail in
the context of the C++ type system. What if T is itself a reference
type? Template libraries have been known to create reference to
reference types via typedefs or type manipulations. According to the
proposed resolution to Core Defect Report 106 , ordinary references obey
the equality T cv1 & cv2 & == T cv12 &, where cv12 is the union of cv1
and cv2. A similar reasoning can be applied to collapse two rvalue
references into one: T cv1 && cv2 && == T cv12 &&.

こいう文書で出てくるcv1やcv2やcv12の数字は何を意味してるんですか?


151 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 17:25:21 ]
区別するため便宜的に番号を振っているだけ。
例えばcv1 = const, cv2 = volatileなら、
vc12 = const volatileだよという話をしたいがためのもの。

152 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 18:57:19 ]
>>151
なるほど。unionは合成の意味ですね。てっきりキーワードもunionかと
思ってしまいました。

153 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 19:59:08 ]
すいません.>>145で示した forward の定義は
正確には>>148さんの書いたとおりです.

>>147
>何が左辺値で何が右辺値なんだかもうわけわからん
戻り値の型が左辺値参照型でない関数の呼び出し構文(の結果)が右辺値で,
それ以外は全て左辺値,という理解である程度通用するかと思います.

>>149
全部把握しているわけではないので推測になりますが,恐らくそうだと思います.
後方互換性の観点から考えても,
パラメタが右辺値参照型以外の場合は従来どおりの deduction になるかと.



154 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 21:19:46 ]
システムの構造体の定義をXML形式で出力したいんだけど、上手い方法があったら教えてださい。
ある構造体は中にも構造体を保持していて、その構造体は別ファイルで定義してるとか、
ifdefやら二重に定義されてるマクロやらで手動でやろうとするともうワケワカメです





155 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 21:46:14 ]
>>153
The next step is to modify the argument deduction to retain information
about the "rvalueness" of the argument: when deducing against a template
parameter of the form A1 &&, deduce A1 as a reference type when the
argument is an lvalue, and a non-reference type otherwise. According to
our T cv1 & cv2 && == T cv12 & rule, this effectively means that the
type of the argument will be A1 & when the argument is an lvalue, and A1
&& otherwise.

どうやら右辺値参照パラメータに対する特別なdeduction ruleみたいですね。

156 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 23:08:28 ]
独自ネームスペースを持つ外部ライブラリを幾つか利用して大きなプログラムを書くようになったら

#include "hoge1.h"
……
#include "hogeN.h"
#include "mylib1.h"
……
#include "mylibN.h"
#include <lib1.h>
……
#include <libN.h>

namespace current_namespace {

using ns1::hoge1;
……
using ns1::hogeN;
……
using nsN::hoge1;
……
using nsN::hogeN;
……

な感じで各ファイルの先頭が埋め尽くされるようになりました。
皆さん、どのように解決しているのでしょうか?

157 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 23:51:26 ]
全てのヘッダを include するヘッダを作って、ソースコードの先頭で
#include "all.h"
とする。


158 名前:デフォルトの名無しさん mailto:sage [2008/01/25(金) 23:53:59 ]
リコンパイルで半泣きコースだな

159 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 00:11:45 ]
リコンパイルで半泣きといえば、いろんな本で冗長インクルードガードが嫌われてるのは何でよ?
VC++2005の #pragma once を使ってる場合ですら200ファイルほどのプロジェクトでリビルド時間が半減したんだけど。


160 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 00:27:07 ]
>>157
using もヘッダん中ですんのか?

161 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 00:29:14 ]
precompiled headerになるようにしときゃいいだろ。

162 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 00:48:04 ]
>>159
よく分からんけど、

#pragma once

よりも、

#ifndef XXXXXXX
#define XXXXXXX

////

#endif

の方がビルド時間が短くなるの?

163 名前:くお [2008/01/26(土) 00:49:00 ]
c++でエクセル用のアドインを作るやり方を教えてください。
よろしくお願いします。



164 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 00:59:44 ]
>>162
#ifndef XXXXXXX
#define XXXXXXX
#include "myhoge.h"
#endif XXXXXXX

とやって include 行を読み飛ばす方法。
myhoge.h にアクセスする必要がない、展開後のファイルサイズが小さくなる、等の理由でビルド時間が短くなることが多い。


165 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:00:16 ]
くおーっ!

166 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:01:52 ]
>>157
all.h に含まれるヘッダのどれか一つでも更新されると all.h を含むファイルが全てコンパイルされる罠。
all.h をプリコンパイルヘッダにしたところで防げません。

167 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:08:25 ]
批判もいいけど先に解決策を示そうぜ。

168 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:11:42 ]
>>164
なるほど。それだとすると、159の
>リコンパイルで半泣きといえば、いろんな本で冗長インクルードガードが嫌われてるのは何でよ?
の理由は、ヘッダファイル使用時にやることが増えるから。かな?

いや、そっちの方が早いってのなら、合理的な理由じゃないとは思うけど
多分159に対する答えは、そんなところだと思う。

169 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:12:55 ]
en.wikipedia.org/wiki/Pragma_once

170 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:39:56 ]
初歩的な質問で申し訳ないのですが、ヘッダファイルの中で行う以下のような
0クリアは問題ないですか?sizeof(this)は正しく計算されます?

class HOGE
{
int a,b,c;
char str[128];

void init(void)
{
memset( this, 0, sizeof(this) );
};
};

171 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:41:18 ]
>>170
やってみりゃいいじゃん

172 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 01:44:07 ]
いえ、できれば構文的に正しいのか知りたいのですが…
テストのクラスで成功しても、他のクラスでは失敗するかもしれないので。

173 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 02:03:15 ]
>>172
コンパイルが通れば、構文的には正しい。
というのは置いといて、
メンバ変数をクリアしたければ、sizeof(*this)とすべき。
そして重要なのは、その方法が使えるのはPOD型だけ。
例えばHOGEに仮想関数を追加すると、動かなくなる。



174 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 02:03:42 ]
構文って意味分かってんのかいな…。

175 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 03:01:40 ]
>>173
詳しく有難うございます。納得できました。

>>174
「構文」は間違いでした。>>173のような事を表したかったのですが、
そういう場合は何と呼ぶべきですかね…

176 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 03:20:13 ]
>>175
つか、何がしたいの?

177 名前:デフォルトの名無しさん [2008/01/26(土) 04:53:51 ]
今タイピングのアルゴリズムでゲーム中に「し」を「si」と「shi」のどちらでも受け付けるとような操作を考えています。
現段階では文字列クラスを用意して双方向リンクリストを使って分岐を操作して居るんですが、どうしてもコードが複雑になってしまいます。
もう少し簡単なアルゴリズムや便利なSTLなどがあったら教えてください。
文字列クラス
class characterData
{
private:
wchar_t ch; // 単語を構成する文字
Databace* follow; // この文字に続く文字へのポインタ
Databace* other; // 分岐文字へのポインタ
Databace* rear; // この文字の前の文字へのポインタ
public:
Databace(); Databace(wchar_t, Databace*, Databace*, Databace*, unsigned char); ~Databace();
// 変数の値を設定する関数群
void setFollow(Databace*); void setOther(Databace*); void setRear(Databace*); void setCh(wchar_t); void setLevel(unsigned char);
// 変数の値を返す関数群
wchar_t getCh() const; Databace* getFollow() const; Databace* getRear() const; Databace* getOther() const;
};
文字列を作るクラス
class createString
{
private:
Databace* end; // 文字列の最後の文字へのポインタ
Databace* div; // 分岐文字がある場合のみendと違う場所を指す
void add(const int n, ...); // n個の文字を追加する
public:
CStrManage(); ~CStrManage();
// elementをローマ字に変換しbaseの後ろに追加する
bool convert(const wchar_t* element, Databace* base);
};

178 名前:デフォルトの名無しさん [2008/01/26(土) 05:00:27 ]
追加用の関数はこうなっています
void createString::add(const int n, ...) {
va_list args_pointer; wchar_t* arg_wchar; size_t length;
va_start(args_pointer, n);
// 文字を分岐させる
for(unsigned char i=0; i<n; i++) {
arg_wchar = va_arg(args_pointer, wchar_t*);
length = wcslen(arg_wchar);
// 分岐用文字列を作成する
Databace cdb; // ダミーの作成
Databace* tmp = &cdb; // 追加先の指定
Databace* rear = NULL; // 現在地の記憶
// 文字の追加
for(unsigned char s=0; s<length; s++) {
Databace* data = new Databace();
if(s==0) { rear = data; } // 追加前の場所を記憶
// 文字データの設定
data->setFollow(NULL); data->setOther(NULL); data->setCh(arg_wchar[s]); data->setLevel(s + 1);
if(s==0) { data->setRear(end); } // 前の文字を参照させる
else { data->setRear(rear); } // 新しく作った文字列の先頭を参照させる
// 文字を追加
tmp->setFollow(data); tmp = tmp->getFollow();
}
// 作成した文字をデータベースに追加する
if(i!=0) {
div->setOther(tmp2->getFollow()); div = tmp; // 作成した文字を追加
div->setFollow(cdb.getFollow()); div = end; // 分岐後の参照先を設定
} else { div->setFollow(cdb.getFollow()); end = div = tmp; }
}
va_end(args_pointer);
}

179 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 05:34:13 ]
>>170
sizeof(this) ってポインタのサイズだと思われ
sizeof(*this) にしないとだめなんじゃね?

180 名前:179 mailto:sage [2008/01/26(土) 05:36:04 ]
って、すでに173で指摘されてた・・・

181 名前:110 mailto:sage [2008/01/26(土) 06:16:08 ]
>>177
std::listを使って一本のリストを作って、リストの各要素のオブジェクトを工夫したほうがいいよ。
リストクラス自作するにしても、これはあまりにも酷い。
せめてコンパイルが通りそうなコードを読ませてくれ。

182 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 11:09:34 ]
>>175
そもそも、クラスの初期化を外部から行なってはいけません。

183 名前:156 mailto:sage [2008/01/26(土) 11:23:55 ]
結局、他の人はどうしてるの?



184 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 11:48:39 ]
折角階層的にネームスペースを宣言しているのに、ユージング宣言し捲くるってどうなのよ。
そんなばかげたことする香具師いないからレスがつかないんじゃね?

185 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 11:54:16 ]
using なんて普通は使わないよな。

186 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:04:47 ]
>>166
all.hにはすべてのヘッダファイルではなく、外部から提供されたライブラリのヘッダだけ入れておけば
基本的に更新することはないんじゃない? (その場合、all.hというネーミングは不適切だね。)


187 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:05:50 ]
目的を既に忘れてるな

188 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:18:43 ]
using 宣言は使うだろ。
using しないとコードが汚くなる。
そこらじゅう ns1::ns2::hoge() とか nsN::nsM::hoge() とかばかりになるぞ。

189 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:21:44 ]
ある程度のプロジェクトではファイルの先頭が #include や using で埋め尽くされるのは避けられないこと。
耐えろ。

190 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:22:45 ]
>>188
おまいはヘッダファイルでも using 使って
迷惑かけるタイプか

191 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:26:55 ]
>>190
どっからヘッダファイルで using なんて考えが出てきたんだ?
*.h と *.cpp では書くものが違うのはあたりまえだろうが。常考。


192 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:32:23 ]
using なんて使わなくても
名前空間のエイリアス作ればいいだろ。

193 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:35:08 ]
>>188
namespace fuga1 = hoge1::hogeA::hogeX;
namespace fuga2 = hoge2::hogeB::hogeY;
namespace fuga3 = hoge3::hogeC::hogeZ;
……
みたいな解決策もある。




194 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:36:58 ]
using は関数増えた時に別の関数が選択される恐れがあるから怖い。
エイリアス作ろうぜ。

195 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:40:22 ]
>>194
例は?
using 指令と違って using 宣言では名前が衝突するとコンパイルすら通りませんが?


196 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:41:57 ]
そもそもネームスペースが上手く使われてる大規模プロジェクトって見たことないな。
パッケージ名を接頭辞に持つプロジェクトの方が上手くいってたりする。

197 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:44:54 ]
>>195
そりゃ嘘を教えられたな。
確かにエラーになることは多いが、エラーにならない事もある。
==========
namespace Hoge { void Foo(); }
namespace HogeHoge { void Bar(); }

using Hoge::Foo;
namespace HogeHoge {
 void Bar() { Foo(); } ← Hoge::Foo
}
==========
namespace Hoge { void Foo(); }
namespace HogeHoge { void Foo(); void Bar(); }

using Hoge::Foo;
namespace HogeHoge {
 void Bar() { Foo(); } ← HogeHoge::Foo
}

198 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:48:05 ]
>>193 の方法でいいんじゃない?
これなら普通は namespace の数 < 識別子の数 なので先頭部分は少し短くなる。
ただし、その代わりにコードは少し長くなる。
どっちにしろ先頭が namespace で埋め尽くされるのは変わらないが。


199 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:54:22 ]
そだよ。エイリアスが一番マシ。

ただ、エイリアスは .cpp のグローバルでのみ作るべし。
名前空間内で作っちゃうとまたややこしい問題が生じる。

200 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 12:59:57 ]
グローバルで using してたら意味ないだろ。
namespace HogeHoge {
 using Hoge::Foo;
 void Foo();
}
で普通にエラーでたぞ。

201 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:04:43 ]
>>200
あらホント。

202 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:04:57 ]
namespace Hoge { void Foo(); }
namespace HogeHoge{
namespace Hoge { void Foo(); }
void Bar(){ Hoge::Foo(); } <- HogeHoge::Hoge::Foo
}

別に間違いようはいくらでもある。

203 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:06:33 ]
名前空間って厄介だよな。



204 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:08:55 ]
>>202
これって防ぎようなくね?
どうすんの? これ。

205 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:11:53 ]
>>204
::Hoge::Foo() でアクセスできるよ。



206 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:12:27 ]
>>205
なるほど・・・。
でも、常日頃から :: から始めないと防げないよな。

207 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:13:53 ]
そもそも他人の名前空間と同じ名前の名前空間を
後から作るという時点で間違いだとは思うが、
開発中に後から導入したライブラリが・・・ということもあるか・・・。

208 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:17:40 ]
ちなみにこんなのも。

namespace Fuga { void Foo(); }
namespace Hoge = Fuga;

namespace HogeHoge {
class Hoge { public: static void Foo(); };
void Bar(){ Hoge::Foo(); } <- HogeHoge::Hoge::Foo();
}

209 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:22:31 ]
名前空間はクラス名・関数名・変数名なんかと違って規約がなかったりするから、結構みんなテキトーにつけてたりする。
酷い話だとグループ全員が自分用の関数を mylibs に入れていた例が...


210 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:25:14 ]
幾何学ライブラリで geom が衝突したりとかだな。

211 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:28:54 ]
かといってJavaみたいにドメインを逆さにするのもなぁ

212 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:32:14 ]
>エイリアスは .cpp のグローバルでのみ作るべし。
グローバルに alias 作るとヘッダが変わったときに突然コンパイルが通らなくなることあるよ。


213 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:35:49 ]
前に関ったプロジェクトは常にフル指定?でメソッドを呼び出すべし

という規約があった

基底クラスのメソッドさえも
Hoge::Foo:Base:Dosomething();

多重継承を多用していたからという事情もあるんだけど

面倒だけど、安全ではある



214 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 13:46:38 ]
その面倒なのがイヤだから using を使いたい、alias を使いたいってんだと思うが。
ぐるっと一周してきた感じだな。

215 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 14:07:49 ]
グローバルにエイリアス量産するぐらいなら名前空間内で using 宣言した方がいいと思う・・・

216 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 18:53:06 ]
しかしだな、エイリアスと別の名前空間が衝突することもあってだな・・・。

217 名前:デフォルトの名無しさん mailto:sage [2008/01/26(土) 19:00:54 ]
無限下降スパイラル

218 名前:177 [2008/01/26(土) 19:12:06 ]
>>181
すいません、文字列クラスがcharacterDataではなくDatabaceでした。
>std::listを使って一本のリストを作って
listやmapを使うことも考えたんですが、リスト化した後のタイプの分岐判定のアルゴリズムが思いつかず断念しました。
なのでその辺のアルゴリズムのアドバイスも出してくれると助かります。
>コンパイルが通りそうなコード
コンパイルも通って動作確認もしてあるので正常に動作しているとは思います。
ただ、これだけ乱雑になると可読性に欠けてバグの温床になりそうなのでアイディアを聞きたいと思った次第です。

219 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 01:56:06 ]
>>175
遅レスだけど、
そういう場合は鼻から悪魔がでますか?って聞けばいいよ。

220 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 11:37:37 ]
//xxx.cpp
namespace
{
namespace ns = long::longlong::longlonglong::ns;
}

void F1()
{
ns::Foo();
}



221 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 13:21:55 ]
template <typename T> //primary template
class Test {
public:
 enum { Result = 1 };
};

template <typename T> //T const に対する partial specialization
class Test<T const> {
public:
 enum { Result = 2 };
};

template<typename T>
void f(T t)
{
 cout << Test<T>::Result << endl;
}

int main()
{
 int i = 1;
 f(i); // @ --> 1が表示される

 int const j = 1;
 f(j); // A --> 1が表示される

}



222 名前:221 mailto:sage [2008/01/27(日) 13:22:31 ]
221です。続きです。

>>221 のtype functionについて疑問があります。
main関数内のAの呼び出しでは、渡している引数の型は確かに int const の
はずですが、結果はprimary templateが呼び出されます。Aでは T が
int const に deduction されて、T const に対する partial specialization
が呼ばれ、結果が2 になると思ったのですが、そうはなりませんでした。
明示的に f<int const>(j); とすれば 2 が表示されます。
何故 A の呼び出しで T が int const に deduction されないのでしょうか?

223 名前:221 mailto:sage [2008/01/27(日) 13:54:47 ]
int const val;
のように変数valを定義した場合、valの型にconstは含まれるのでしょうか?

int const& ref;
の場合は、refの型は int const& となりconstは含まれますよね?



224 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 15:46:48 ]
int const val; と const int val; は等価。
val の型に const は含まれる。

225 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 15:57:41 ]
>>222
パラメータリストのconst修飾は関数の型としては無視される、
ということからだろうと思われる
たとえばvoid f(int);とvoid f(int const)の型は全く同一になる
f<int const>(j); とすれば 2 が表示されることに保証があるのか
俺は知らない

226 名前:221 mailto:sage [2008/01/27(日) 16:45:57 ]
レスありがとうございます。

>>224
>int const val; と const int val; は等価。
それは知ってます。
やはり型の一部ですよね。

>>225
>たとえばvoid f(int);とvoid f(int const)の型は全く同一になる
value functionに関するそのルールは知っています。
このプログラムはvalue functionではなく、type functionなので
引数のdeductionの問題になると思います。f<int const>(j); は
明示的に型を指定しているのでpartial specializationが使用
されることは間違いないです。ただ、constが型の一部であるにも
関わらず、int const型のテンプレート引数である j を渡しても
specializationが使用されていないのが理解できません。

結果を見る限り、const修飾子が無視されてint引数として扱われてること
になりますが、これはテンプレートの標準における正しい仕様なのでしょ
うか?

VC++ 2008 と g++ v4 ともに同じ結果でした。


227 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 16:49:54 ]
そもそも const int を int な引数の関数に渡せるしね。
規格でどうか知りたいなら、規格を読むのが一番だ。

228 名前:221 mailto:sage [2008/01/27(日) 17:09:22 ]
>>227
それはvalue functionのパラメータ及び引数のルールであって、
テンプレートのtype parameterのdeductionはまた別の問題のよ
うに思います。もう少し規格を見てみます。


229 名前:221 mailto:sage [2008/01/27(日) 17:12:18 ]
>>227
>>228は撤回します。
確かにそれが理由のような気がします。
そうすると、const int と T を比べると T が intに
deductionされるのも頷けます。

230 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:14:12 ]
>>226
>partial specializationが使用 されることは間違いないです

ああそりゃそうか

>これはテンプレートの標準における正しい仕様なのでしょうか?

14.8.2 -3-にあった


231 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:17:06 ]
手元にドラフトがあるのでそれで調べてみたが、14.8.2.1 p2 にそれらしきものが。

14.8.2.1 Deducing template arguments from a function call
If A is a cv-qualified type, the top level cv-qualifiers of A's type are ignored for type deduction.

232 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:18:11 ]
あー、そっちかもしれん。>>230

233 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:19:04 ]
>>226
type function とか value function とか、何の方言?
意味がわからない。



234 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:20:09 ]
最新のドラフトを見ると怖いことが書いてあった

[ Note: f<int>(1) and f<const int>(1) call distinct functions even though both of the functions called have the
same function type. .end note ]

235 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:24:04 ]
>>234
まあ明示的に指定する分には違っててもいいんじゃね?

236 名前:221 mailto:sage [2008/01/27(日) 17:34:09 ]
>>230
>>231
>>232
>>233
>>234
>>235
みなさんレスありがとうございます。

>>231
まさにそれかと思います。同じことがJosuttisのC++ Templateにも
書いてありました。

こういう事情のようでです。

template<typename T> void f(T);
template<typename T> void g(T&);

int const ci = 123;

f(ci); // T is int
g(ci); // T is int const

すっきりしました。

237 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 17:40:02 ]
int const& の const はトップレベルの const じゃないからそうなるわな。なるほど。

238 名前:221 mailto:sage [2008/01/27(日) 17:47:45 ]
>>233
詳しいことは知りませんが、
現段階で標準で規定された言葉ではないと思います。
テンプレートの本に書かれていました。
value functionはいわゆる通常の関数を指します。
パラメータがtype、引数が値。
type functionとは、通常クラステンプレートで
実現されるものらしいです。
パラメータがテンプレートパラメータ、引数がtype。

struct Widget{};
Test<Widget>::Result;

>>221のTestクラステンプレートの場合、Widgetが引数で
type functionの戻り値がTest<Widget>::Resultと考え
ると通常の関数のように関数とみなせるというもだと
理解してます。

239 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 18:03:50 ]
>>238
「テンプレートの本」ってどれだ?

普通に「関数」と「クラステンプレート」って言ったほうがいいと思うよ。
意味の違いを正しく表している呼び名だとは思えないからね。
後者は「(テンプレート)メタ関数」とか呼ばれるもののような気もするなぁ。

240 名前:221 mailto:sage [2008/01/27(日) 18:36:02 ]
>>239
ここでいうtype functionとは
最近の言葉で表せばメタ関数でしょうね。
Boost::mplなどの最近のメタプログラミングで
使われていますが。

本はC++ Template The Complete Guideです。
著者は標準化委員会の現メンバーでもあり
信用できないものではないと思います。

通常の関数と対比して、コンパイル時に型を引数
とする”関数”という概念的に上手い言葉だと感じ
ているので自分はなるほどと思いました。


241 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 19:21:38 ]
>>240
メタ関数でいいならそう言ったほうがいいでしょ。
わざわざ廃れた用語を使い続ける理由もない。

242 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 19:32:18 ]
meta function == type function
別に正式な名前じゃないけど、
type functionってのはそこそこみる表現だから覚えておいてもいいと思うよ

243 名前:デフォルトの名無しさん mailto:sage [2008/01/27(日) 23:07:12 ]
>>241
別に廃れてるわけではないよ。
概念を表した言葉だから。



244 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 11:46:24 ]
適当なオブジェクトのポインタが与えられたとき、そのオブジェクトのクラスがある特定の
名前と引数のタイプを持ったメンバ関数を持つときに限りその関数を呼んで処理したい
のですが、C++ で可能でしょうか?

あ、オブジェクトは必ずしも共通のスーパークラスを持たないとします。要はそういう
場合でも仮想関数的なことをしたいというか...
その特定のメソッドをもつ別クラスを作って、それを全てのオブジェクトで多重継承、
というのも考えているのですが、ちょっとダサいかな? と思って。あとソースのないクラス
では無理ですよね(今のところはソースのあるクラスだけでいいんですが)。

そもそもこんなことを考える事自体ナンセンス、と言われるとアレなんですがw

245 名前:デフォルトの名無しさん mailto:sage [2008/01/29(火) 12:35:21 ]
ポインタの型がテンプレート引数で与えられているならば、可能






[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧](*・∀・)<95KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef