LPCTSTRへのキャスト

[戻る]
hirocco 2011/04/05(火) 11:13:49
CString strTest  ="あいうえお";という変数があって,
void Cxxx::Func(LPCTSTR value);というメソッドに渡す場合は,

Cxxx::Func( (LPCTSTR)strTest );
引数の場合だけでなく代入の場合でも同様な感じです
LPCTSTR value  =(LPCTSTR)strTest;

と明示的にoperatorを
"今でも"呼び出すべきなのでしょうか?

それともこの場合は暗黙にキャストされるようになって,
(LPCTSTR)へのキャストは不要なのでしょうか?

どちらでも通ってしまうのでノーマークだったんですけど...
よろしくお願いします

VS9 XP/Vista/7

仲澤@失業者 2011/04/05(火) 11:48:10
明示的にしようと、省略しようと
CSimpleStringT::operator PCXSTR()
キャストオペレータが働くのですが、実はこの子はデータポインタ
を戻す以外何もしないので。
結局「何もしない」という事において、どう書いても同じという認識です。

tetrapod 2011/04/05(火) 14:33:02
> それともこの場合は暗黙にキャストされるようになって,
> (LPCTSTR)へのキャストは不要なのでしょうか?
言語仕様書上、キャストっていうのは「変換をソース上に明示すること」なので、
「暗黙にキャスト」ってのは用語が変。
「暗黙の変換」が行われる、のであれば厳密な表現になる。

> "今でも"呼び出すべきなのでしょうか?
いらない。俺なら明示しない。

以下は難しい話なので興味があるなら読んでくれ。

誤解してはならないのは
 (type) キャストは operator type() の呼び出しではない
ということだ。

提示サンプルを厳密に読み解こうとすると、言語仕様上、2点の理解が必要で、
・関数の多重定義がある場合の、最適候補の選定
・候補選定後の、(暗黙の)型変換

意味が無い変態的な例
struct hoge_t { ... // 何かメンバ変数類が存在して
 operator double() const { ... } // double への変換関数がある
};
としよう。この hoge_t は operator float() を持っていない。が
hoge_t h; // コンストラクタが初期化している
int x=(float)h; // 反則すれすれだが合法
はまったく問題なくコンパイルできる。実動作は
h.operator double() const の呼び出し→ double->float 変換→ float->int 変換
で、この例で何をどう書けばよかったのか、は、元のコードの作者の意図次第。
# 単なる思い付きの例なので正解は無いわけだが

提示例で型変換を明示したいのであれば
 func(strTest.operator LPCTSTR()); // とすべきであろう。

hirocco 2011/04/05(火) 15:07:37
http://msdn.microsoft.com/ja-jp/library/ms908328.aspx

この辺を読んで混乱してます
ここでは"明示的なキャストをしなさい(you must cast it explicitly as LPCTSTR.)"と
あって
でも,皆さんは
> どう書いても同じという認識です。> いらない。俺なら明示しない。
と教えてくれます

ひょっとして,
http://msdn.microsoft.com/ja-jp/library/ms908328.aspx
で言っているのは,実は_tprintfに限っての話なんでしょうか???

hirocco 2011/04/05(火) 15:09:33
P.S.
追加です
http://msdn.microsoft.com/ja-jp/library/ms908328.aspx
では
型変換ではなくキャストと書いてあるんですけど,
英語では同じものなんでしょうか?

hirocco 2011/04/05(火) 15:12:04
読み違えてました
追加部分は無かった事で。。。

tetrapod 2011/04/05(火) 16:19:12
> 実は_tprintfに限っての話なんでしょうか???
Yes (厳密に言えば、可変個数引数を使うところ)

> ・関数の多重定義がある場合の、最適候補の選定
が可能なのは、あらかじめ関数宣言で引数の型が明示されている場合に限られる。

printf や CString::Format などの可変個数引数部分 ... 領域では、
言語仕様上 C 互換の [既定の型昇格] のみが行われることになっている。
この可変個数引数部分に「非 POD 型」を渡すことは禁じられている (5.2.2-7)

なので可変個数引数部に CString というクラス型 (非 POD) を渡すことはできない。
CString を operator TCHAR* でポインタ型に変換したら渡せるようになるので、
キャストを明示せよと書かれているわけだ。

繰り返すがキャストは必ずしも operator TYPE() の直接呼出しではないので、
提示 MSDN ページのサンプルは、より厳密には
CString str = "Some Data";
str.Format(_T("%s%d"), str.operator const TCHAR(), 123));
であるべき。

hirocco 2011/04/05(火) 17:27:23
[[解決]]
なるほど,すごく理解できました
可変個数引数部分には何が入ってくるのかと考えると,
OldData型で閉じているほうが楽ですものねぇ
でも,CString::FormatってCStringのメソッドなんですから,
「const CString&」型の引数くらい判断して受け付けてくれてもいいのにねぇ

基本的にはLPCTSTRに代入?する場合は「(LPCTSTR)」はつけないでよい
でも,POD待ちな引数には「(LPCTSTR)」はつけてねということですね

ありがとうございました

古いスレッドには追加発言できません。