もう20時か、
2ちゃんねる ■掲示板に戻る■ 全部 1- 最新50 [PR]女性の自宅ナマ映像を無料公開[PR]  

C++相談室 part63

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

前スレ
C++相談室 part62
http://pc11.2ch.net/test/read.cgi/tech/1211900039/

525 :デフォルトの名無しさん:2008/08/27(水) 14:44:02
いい加減なコードが通るコンパイラがいいのか?

526 :デフォルトの名無しさん:2008/08/27(水) 15:22:07
いい加減な動作をしそうな気がする

527 :デフォルトの名無しさん:2008/08/27(水) 15:23:15
いい加減な人間が実行するから問題なし

528 :デフォルトの名無しさん:2008/08/27(水) 15:44:36
>>523

そんなコンパイラ聞いたことないぞ

専門学生が卒業制作で作ったようなやつか?

529 :デフォルトの名無しさん:2008/08/27(水) 15:46:25
インライン展開についての質問です
あるクラスのオペレータのオーバーロードで

__inline const hoge &hote::operator + () const;
とするとインライン化されるのですが

__inline const hoge hote::operator + () const;
とするとインライン展開されずに関数呼び出しになります

内部処理は*thisを返しているだけです
インライン展開できない条件を調べてみたところ、以下の条件が当てはまるのかと思うんですが
「コピー構築されたオブジェクトを値で受け取る関数を、-GX/EHs/EHa でコンパイルした場合。」
良く理解できず、解決方法が分かりません。どうすれば値渡しでインライン展開できるでしょうか

530 :デフォルトの名無しさん:2008/08/27(水) 16:02:44
細かいことは気にするな。
それよりやるべきことはいっぱいある。

531 :デフォルトの名無しさん:2008/08/27(水) 16:14:02
細かいミスは気にしないでください
空のデストラクタを定義していたんですが、それをやめたらうまくいきました。
値渡しだとデストラクタが走るのは分かるんですが、インラインできない理由はよく分かりません^^;

532 :デフォルトの名無しさん:2008/08/27(水) 16:19:19
ということは、例外が投げられたときにデストラクタを呼ぶコードを吐かないといけないからだな。
529にあるコンパイラオプションはどれも例外処理を使用可能にするものばかりだ。

533 :デフォルトの名無しさん:2008/08/27(水) 16:39:14
なるほど、そういうことでしたか。スッキリしました^^

534 :デフォルトの名無しさん:2008/08/27(水) 20:25:40
マトリョーシカってプロトコルスタックに例えられることがあるよね。入れ子ってことで。

535 :デフォルトの名無しさん:2008/08/27(水) 21:46:35
いや、ないよ

536 :デフォルトの名無しさん:2008/08/27(水) 23:13:45
にじゃなくてがだろ

537 :デフォルトの名無しさん:2008/08/27(水) 23:58:52
文字列リテラルってstring型に暗黙変換されますよね?
しかし

bitset<5> bs("10101"); //エラー
bitset<5> bs(string("10101")); //OK

という結果になるのですが、なぜ前者のケースでstring型に暗黙変換
されないのでしょうか?

538 :デフォルトの名無しさん:2008/08/28(木) 00:03:58
引数がconstだから

539 :デフォルトの名無しさん:2008/08/28(木) 00:05:20
暗黙変換されないって

540 :デフォルトの名無しさん:2008/08/28(木) 00:07:13
>>537
explicitだから

541 :デフォルトの名無しさん:2008/08/28(木) 00:41:44
string str = "abc";

が可能なので、const char* からstringへの暗黙変換は定義されてると
思うのですが。

542 :デフォルトの名無しさん:2008/08/28(木) 01:01:46
ん、bitsetのbasic_stringを受け取るコンストラクタがテンプレートだからじゃないの?

template<size_t N>
class bitset {
public:
 // こっちが本物:エラーになる
 template <class CharT, class Traits, class Allocator>
 explicit bitset(const basic_string<CharT, Traits, Allocator>&) {}

 // 確認用:こっちはOK
 explicit bitset(const string&) {}
};

const char*からでは、basic_stringのテンプレートパラメータを推論できない

ちなみにC++0xではconst char*を受け取るコンストラクタが追加される

543 :デフォルトの名無しさん:2008/08/28(木) 01:05:43
>>542
ありがとうございます。

メンバテンプレートのコンストラクタだからですね。

544 :デフォルトの名無しさん:2008/08/28(木) 02:04:29
クラス定義の末尾で ; を落としただけなのに
「istreamが再定義されています」とかわけの分からないエラーが出るのは悔しいです。
(クラス定義の次の行にstd::istreamを戻り値に持つ関数が定義されている)
ちゃんと「クラス定義の末尾に ; を付け忘れてますよ。ふふふ。」と優しく教えてください。


545 :デフォルトの名無しさん:2008/08/28(木) 02:06:43
>>544
大丈夫、そのうち自身の脳みそがそう指摘してくれるようになるから。

546 :デフォルトの名無しさん:2008/08/29(金) 10:48:45
テンプレートについて質問があります。
以下の[Base.h]でDerivedを宣言した時にBase<T>の型は解決して
[Base.cpp]ではBase<int>::funcがコンパイルされると思うのですが、
リンクエラー(Base<int>::funcがない)になります。
これはどう理解すればよいでしょうか?

[Base.h] // ヘッダファイル
template <typename T> struct Base { T func(void); }; // テンプレートクラス
struct Derived : Base<int> {}; // 型の解決(?)したテンプレートクラスを継承したクラス

[Base.cpp] // 実装
#include "Base.h"
template<typename T> T Base<T>::func(void) { return 0; }

[main.cpp]
#include "Base.h"
int main(void) {
 Derived d;
 d.func(); // リンクエラー
return 0;
}


547 :デフォルトの名無しさん:2008/08/29(金) 11:03:39
テンプレート全般は、普通、宣言と実装を別けられない。
ヘッダにインラインで書くべき。
exportキーワードで別けられるコンパイラもあるが、gccもBCCもVCもダメ。

548 :デフォルトの名無しさん:2008/08/29(金) 11:05:33
>>546
http://www.google.com/search?q=C%2B%2B テンプレート ヘッダ 実装

549 :546:2008/08/29(金) 11:26:32
>>547-548
どうも。
テンプレートでは宣言と実装を分けないという基本的な考え方は理解しているのですが、
それは結局はコンパイル時に型解決ができないからですよね。
>>546のコードはどうして型解決ができていないのかというのが質問の趣旨です。
例えば[Base.cpp]内で
Base<int> dummy;
とダミー変数を用意してもダメでした。

550 :デフォルトの名無しさん:2008/08/29(金) 11:31:11
コンパイラの気持ちになって考えればよく分かる

551 :デフォルトの名無しさん:2008/08/29(金) 11:33:14
なんか基本が出来てないような気がするが・・・
実装というのは関数の実装だ。
template<typename T> T Base<T>::func(void) { return 0; }
↑これがダメなの。

型を全部指定したらそれはもはやテンプレートではない。
struct Derived : Base<int> {.....のメンバ関数はcppに実装を書いても通る。

552 :デフォルトの名無しさん:2008/08/29(金) 11:42:24
Base.cpp に template class Base<int>; って書くといいよ

553 :デフォルトの名無しさん:2008/08/29(金) 11:44:06
だよな…
それなら最初からint func(void)にしとけばいいじゃんってことになるからな

554 :546:2008/08/29(金) 11:48:58
# 結果を書いている途中で>>551以降のコメントが…。
# とりあえず載せます。

コンパイラの気持ちは結局わからなかったのですが、
結果は明らかになりました。

[Base.cpp]
#include "Base.h"
template<typename T> T Base<T>::func(void) { return 0; }
Base<int> dummy;
// ↑これだけだとアウト:オブジェクトファイルBase.oの中身は空っぽ
// ↓これを加えるとOK:Base.o
void func(void) { dummy0.func(); }

つまり、コンパイルされるのは用いられている関数のみでした。
クラスインスタンスを生成しても、使われなかった関数はコンパイルされない、というのは意外でした。


555 :546:2008/08/29(金) 11:50:54
>>552
どうも!それが一番の解決策でした!


556 :デフォルトの名無しさん:2008/08/29(金) 11:59:04
クラスhogeにメンバa,b,cがあり、hoge h1,h2,h3を作ったとして、h1=h2+h3とやった際に
h1.a=h2.a+h3.a
h1.b=h2.b+h3.b
h2.c=h2.c+h3.c
と同等のパフォーマンスを出したく、調べていたらRVOと言う方法を見つけたんですが
__inline hoge hoge::operator + ( const hoge &v ) const
{ return vec3(x+v.x,y+v.y,z+v.z); }

とした場合、アセンブラ命令で15命令になってしまいました
RVOではオブジェクトの作成&削除は避けれても値の複製事態は避けられないのでしょうか?

557 :デフォルトの名無しさん:2008/08/29(金) 11:59:12
質問です。
関数ポインタについてなのですが

void test(IHoge*(func)(const char*));
という関数に、
CHoge* hoge(const char*);
を渡すことができず、エラーになってしまいました。

IHogeはCHogetの基底クラスのため、暗黙のアップキャストが行われるのを期待したのですが・・・
hoge関数の返り値を変更せずに解決する方法はありませんでしょうか?


558 :デフォルトの名無しさん:2008/08/29(金) 12:18:07
funcの前に*

559 :デフォルトの名無しさん:2008/08/29(金) 12:28:22
>>557
IHoge* hogeWrapper(const char* s) { return hoge(s); }
を渡せばいいんじゃない

560 :デフォルトの名無しさん:2008/08/29(金) 13:03:33
>>558
うーん、足してみたけどダメでした

>>559
結構な数のラッパーを書くことになるので、避けたいところです

561 :デフォルトの名無しさん:2008/08/29(金) 13:23:53
>>557

キャスト使うとか?
↓こんな感じ。


// 関数ポインタの型をtypedefしておく。
typedef IHoge*(*RetIHogeFun)(const char*);

// test関数に渡すときにキャストする。
test((RetIHogeFun)hoge);


562 :デフォルトの名無しさん:2008/08/29(金) 13:41:03
>>561
できました!
なるほど、関数ポインタ型にキャストしてやる(書きやすいようにtypedefもしてやる)わけですね。
ありがとうございます。


563 :デフォルトの名無しさん:2008/08/29(金) 15:39:21
たとえばvectorのメンバを持ったクラスを設計するとき
ヘッダーでincludeせずcppの中でvectorをincludeする書き方
ってどんなものがあるでしょうか。
とりあえずメンバを*voidにしておくくらいしか思い浮かばない・・。

564 :デフォルトの名無しさん:2008/08/29(金) 15:45:40
「pimplイディオム」でググれ

565 :デフォルトの名無しさん:2008/08/29(金) 15:47:38
pimplイディオム

566 :デフォルトの名無しさん:2008/08/29(金) 15:55:52
あれタルいよな

567 :563:2008/08/29(金) 16:39:25
pimplイディオム・・・なんとなくわかったようなわからないような。
もうちょっと学んでみるけど、これ使ってもポインタにするしかない?
それtも書き方次第なのかな。

568 :デフォルトの名無しさん:2008/08/29(金) 18:19:16
vectorに限らず、実体をメンバに持つには、vectorのサイズがわからないと無理。
サイズを知るには実装部を見せるしかない。

なお、ポインタの他に、関数の引数や返り値とする場合も
サイズなしで宣言だけで可能。
でもメンバは無理。
(無茶するならExceptionalC++にchar[]で確保する方法が一応あったけど)

で、おまいが欲しているのはvectorの実体か?
void*を持たせて代わりにするなんてのは、vectorへのポインタ以外にあり得ないが。

569 :563:2008/08/29(金) 19:44:51
>>568
そう、cppでキャストして使う方法。
方法ということで*voidと書いたけど、もしpimplイディオムで実体持たせながら実現
できるならポインタがらみの問題も排除できるかな〜と。
簡単にはいかないようなので、ポインタがらみで問題を増やすなら素直にinclude
することにします。ありがとう。
pimplイディオムというものを知らなかったので勉強になりました。

570 :デフォルトの名無しさん:2008/08/29(金) 20:21:48
先生お願いします
Win32ではない標準のC/C++で他アプリを起動するには
Cのexec system popen のどれかを使用すると調べましたが
他にどのような手段があるのかご教授頂きたく

検索してもWindowsAPI関連サイトが多すぎて歯がゆいっす

571 :デフォルトの名無しさん:2008/08/29(金) 20:57:04
spawnとか?
どれも最終的にはCreateProcessが呼ばれる
気にしてどーすんの

572 :デフォルトの名無しさん:2008/08/30(土) 00:38:56
標準のC/C++にはsystem()しか無いだろ

573 :デフォルトの名無しさん:2008/08/30(土) 03:47:15
エラー処理や完了待ちを考えると標準でがんばるのはつらい

574 :デフォルトの名無しさん:2008/08/30(土) 04:00:20
いや、system() さえあれば何でもできるぞw

146 KB [ 2ちゃんねる 3億PV/日をささえる レンタルサーバー \877/2TB/100Mbps]

■ おすすめ2ちゃんねる 開発中。。。 by FOX ★
このスレを見ている人はこんなスレも見ています。(ver 0.20)
サクラエディタふぁんくらぶ part10 [ソフトウェア]
FreeBSD 初心者スレッド [UNIX]

新着レスの表示

掲示板に戻る 全部 前100 次100 最新50
名前: E-mail (省略可) :


read.cgi ver 05.0.7.3 2008/07/26
FOX ★ DSO(Dynamic Shared Object)