C++相談室 part62at TECH
C++相談室 part62 - 暇つぶし2ch809:デフォルトの名無しさん
08/07/16 21:46:08
>>805
ありがとうございます。
そのメタ関数の作り方を教えていただけないでしょうか?
あるいは、そのようなテンプレートプログラミングについて解説してあるサイトを紹介してくださると助かります。

810:デフォルトの名無しさん
08/07/16 21:46:10
>807
すみません。移動します。

811:デフォルトの名無しさん
08/07/16 21:57:08
>>808
boost::MPLにはあまり詳しくないのですが、
Xが整数型なら X<T>::type == Y<T> 、そうでなければ X<T>::type == Z<T> ということでしょうか。
組み込み型か否かというような判断ではなく、
例えば「Tがメンバにbegin()とend()を持つか否か」や「Tがメンバにoperator()を持つか否か」で、
使うテンプレートを分岐させたいのですが、解決方法があれば幸いです。

812:デフォルトの名無しさん
08/07/16 22:27:34
>>811
任意の型について
>「Tがメンバにbegin()とend()を持つか否か」や「Tがメンバにoperator()を持つか否か
を判定することは出来ないと思います

x.begin()

と呼ぶのではなく

begin(x)

などと呼んで型ごとにオーバーロードを用意するとかではダメですか?
Boost.Range がこの方法を採用して begin を持つ型にひ持たない型にも対応しています
私もたまにそうします

813:デフォルトの名無しさん
08/07/16 22:38:50
>>812
うーん、やはり無理ですか。

コンテナに対するオペレータのオーバーロードを考えていて、
コンテナが高階か1階かによって適用させる関数を変えたいと考えていたのですが、
どうもそういう発想に基づかない実装が必要なようですね。

ありがとうございました。


814:デフォルトの名無しさん
08/07/16 22:45:39
>>799, >>802
だーかーらー、原著者がかましたボケかどうか確認しろつーの

815:デフォルトの名無しさん
08/07/16 23:03:42
>>813
役に立たないかもしれないけど、要件はクリア?
#include <iostream>

template<class T> struct Y { T m; };
struct Z {};

template<template<class T> class C>
struct X
{
template<class A>
static void f(C<A> x)
{
std::cout << "f(C<A>)" << std::endl;
f(x.m);
}

template<class B>
static void f(B x)
{
std::cout << "f(B)" << std::endl;
}
};

int main()
{
Y<Y<Z> > y;
X<Y>::f(y);
return 0;
}


816:デフォルトの名無しさん
08/07/17 00:17:58
>>815
この方法だと、型を1つ引数に取るテンプレートクラスか否かで分岐させているということでしょうか。
できればそれに限らないコンテナ(boost::arrayとか)も一括して扱いたいのですが、
確かにvectorやdeque, listに関してはこれで扱えそうですね。

教えてくださってありがとうございます。


817:デフォルトの名無しさん
08/07/17 22:37:21
テンプレートクラスのインスタンス化についての質問で、
以下のようなことがしたいのです。
※以下の全ての例は当然コンパイルはできません。


// 動的にテンプレートの型
list* getList(int n) {
if(1 == n) {
// int型のリストをreturn
}

if(2 == n) {
// double型のリストをreturn
}
}

int main() {

// 型情報を持たないlistクラスの変数を用意(したい)
list* x;

int num;
std::cin>>num;

// キーボードで入力した値によって型を変える
x = getList(num);

}

このような処理を行いたいのですが、どうにかならないでしょうか…
JavaにおけるObjectクラスのようなクラスがあればいいのですが。

818:817
08/07/17 22:37:52
私が考えてみたのは

(1)typedefを使う
(2)マクロを使う

で、どちらも上手くいきません。

(1)については、

// typedef の前方宣言(をしたい)
typdef typ_t;

// 動的に型情報を決定(これだとスコープ的にダメ?)
if(1 == n) {
typedef int type_t
}

if(2 == n) {
typedef double type_t
}

// 動的に定まった型を用いてインスタンス化
list<type_t> x;

こんな感じにできないかと思ったのですが、
宣言がの方法がわかりませんでした。(できない?)

819:デフォルトの名無しさん
08/07/17 22:38:30
(2)については

// とりあえず何か型を設定
#define TYPE_T int

// 動的に型情報を決定
if(1 == n) {
#undef TYPE_T
#define TYPE_T double
}

if(2 == n) {
#undef TYPE_T
#define TYPE_T char
}

// 動的に定まった型を用いてインスタンス化
list<TYPE_T> x;

これは n の値によらず最後に #defile された値
が常に適用されてしまい、ダメでした。
(今の場合でしたら常に list<char> が生成されてしまう。)

もう本当にお手上げ状態でして、みなさんのお知恵を
お借りしたいと思っている次第でございます;;

何卒よろしくお願いします

820:デフォルトの名無しさん
08/07/17 22:39:41
>>818最後の行

×宣言がの方法が
○前方宣言の方法が

821:デフォルトの名無しさん
08/07/17 22:57:57
>>819
テンプレートクラスを使わずに普通のクラスで対処したらいけないの?

class list { /* listの定義 */ };;
class IntegerList : public list { /* IntegerListの定義 */ };
class DoubleList : public list { /* DoubleListの定義 */ };

list* getList(int n) {
    if ( n == 1 ) { return new IntegerList(); }
    if ( n == 2 ) { return new DoubleList(); }
}

822:デフォルトの名無しさん
08/07/17 23:15:06
インスタンス化クラスの型はコンパイル時に解決するから、実行時の多態性を実現する目的には向かない。

823:デフォルトの名無しさん
08/07/17 23:20:01
テンプレートはコンパイル時の問題を解決するための道具です
実行時には役立ちません

実行時の問題は実行時用の道具で対処したほうが良いでしょう

824:デフォルトの名無しさん
08/07/17 23:29:17
>>821
元々の目的が
「テンプレートクラスの型指定を実行時に動的に行いたい」
ということですので、それだと本来の目的に合わないのです。

が、>>822 >>823 さんの仰るように、そもそも本来の目的の
方向性が良くなかったようで…。
一度構成を考え直してみたいと思います。

みなさん、どうもありがとうございました。

825:デフォルトの名無しさん
08/07/17 23:53:05
boost.variantじゃ駄目なのか

826:デフォルトの名無しさん
08/07/18 04:24:38
今、とある解説書でC++の例外を勉強しているのだが、投げられた例外を
受け取る例外ハンドラがない場合、terminage()が呼ばれabort()が呼ばれると。
abort()は何の後処理もせずプログラムを終了させるから具合が悪いという
ことが書かれているのだが、プログラムが終了すればすべてメモリは解放
されるのと違うの?プログラムが終了してまで、何か禍根が残るなんてこと
あるの?

827:826
08/07/18 04:25:20
ミス
terminage() → terminate()

828:デフォルトの名無しさん
08/07/18 04:33:50
>>826
ファイルシステムとかデータベースとか。

mkdir() を使ったロックなんかがわかりやすいかな?

829:826
08/07/18 04:39:16
レスどうも。
つまりプログラムとは独立したなんらかのリソースを操作する場合に
影響が残るということか…

830:デフォルトの名無しさん
08/07/18 04:54:12
VC++2008で
void f() throw( hoge1, hoge2, hoge3);
みたいな例外指定ってサポートされてないんだね。
標準C++勉強してると、意外と最近のコンパイラが標準準拠していない
ことに気づく。

831:デフォルトの名無しさん
08/07/18 07:57:37
むしろ準拠しなくてもOSが「問題ないぜ!掛かって来い冷害!」

832:デフォルトの名無しさん
08/07/18 13:08:34
初心者で申し訳ないのですが、
googleのsparse_hash_mapを使おうとして、マニュアル通り
#include <iostream>
#include <google/sparse_hash_map>
using namespace std;
using google::sparse_hash_map;
..
int main () {
sparse_hash_map<const char *, int, hash<const char *>, eqstr> months;
とすると、
'hash' was not declared in this scope
と、hash<const char *> すら定義されていないと言って怒られてしまいます。
hash_mapの場合も同じだったのですが、どうするといいでしょうか。
環境は g++ (GCC) 4.1.1 20070105, Linux FC6です。
よろしくお願いします。

833:デフォルトの名無しさん
08/07/18 13:25:34
#include <ext/hash_fun.h>
を追加してみてはいかがでしょう。

834:デフォルトの名無しさん
08/07/18 14:28:03
>>833
ありがとうございます。
もう一度追加してみたのですが、エラーメッセージは同じのようでした。
ちなみに using __gnu_cxx; したり、__gnu_cxx::hash<const char *>と
すると、もの凄いエラーメッセージが出ます。。

835:832
08/07/18 18:20:56
すみません、自己解決しました。
上のコードの struct eqstr の持つ比較関数
bool operator() (const char *a, const char *b) const
で、最後の const が抜けていたのが原因のようでした。
using namespace __gnu_cxx; で const を加えると、問題なく通りました。
# たったそれだけで長大なエラーメッセージが表示されるとは、
C++、恐ろしい子・・・!!

836:デフォルトの名無しさん
08/07/18 18:31:34
最初の方の数個のエラーだけ見て推測すりゃ良いだろ。
コンパイル時間と長大なエラーメッセージに怖気づくなよ。

837:デフォルトの名無しさん
08/07/18 23:32:51
>>830
VCはずっとサポートされないままだね。(他は知らないけど)
やっぱ難しいんかな。

838:デフォルトの名無しさん
08/07/18 23:45:04
          ζ
         / ̄ ̄ ̄ ̄\
       /         |
       | ⌒  ⌒   /|
       | (・)  (・)   |||||||
       | ⊂⌒◯-----∂)___   ___
       | ||||||||_     /     ゙Y"     \
         \ヽ_/ \/              \
         \    /                 \
          / ̄ ̄ ̄ ̄)        *      ( ̄ ̄ ̄ ̄)
         |    ─<         |\      >─   (
         |      )     /  (|ミ;\    (      )
         ヽ    ̄ ̄)    /(___人|,iミ'=;\  (  ̄ ̄   )
         /" ̄ ̄ ̄ ̄   /    《v厂リiy\  ̄ ̄ ̄ ̄\
         /        /        ゙|,/'' v:,,、.¨)z,_       \
        /       /         ミ/ .-─ .゙》z、      \
        /      /           〔」″ノ‐ 、u ¨\      )
       (      /             ゙|, ..冫 .rー    ̄\_    |
        |      〔              ミ./′   ..r-ー __,,ア┐  |
        |      |              {. .,,,,   .′  .´′ .¨\|
        |       |              ∨   ノ冖′ =vvvvvv¨\
        |     /               ミ.   ,i'           .゙\_
        |     /                .{.  ノ  ,r¬″       .¨\

839:デフォルトの名無しさん
08/07/18 23:49:41
>837
実装するだけなら全く難しくないと思うが
関数に try, catch 差し込んで unexpected 呼ぶだけでしょ

840:デフォルトの名無しさん
08/07/19 00:32:21
例外指定なんて誰も使わないから別にいい

841:デフォルトの名無しさん
08/07/19 16:56:54
Javaは例外指定必須だけどうっぜえ割に大してバグが減るわけでもない
はっきり言って全くいらない機能

842:デフォルトの名無しさん
08/07/19 23:51:23
同意。C#の設計者もアレあんまし意味無いだろって言ってる品。
URLリンク(www.artima.com)

843:デフォルトの名無しさん
08/07/20 07:52:16
>>838
これって遠近法で描かれたウンコなのかドリルなのか気になる

844:デフォルトの名無しさん
08/07/20 09:28:32
激突
アナル vs ドリル

845:デフォルトの名無しさん
08/07/20 10:54:04
new/delete演算子をオーバーライドしたいのですが、
これらの中からもとのnew/deleteを呼ぶにはどうしたらよいですか?


846:デフォルトの名無しさん
08/07/20 14:57:11
置かれている状況が分からないから何とも言えないけど、
::operator newと::operator deleteでどうよ。

847:デフォルトの名無しさん
08/07/20 17:09:26
operator newをオーバーライドしたなら、必要なのはメモリの固まりなわけで、
mallocでも呼んどきゃいいんでね?

848:デフォルトの名無しさん
08/07/20 17:58:46
>>847
コンストラクタを呼びたいんじゃね?

849:デフォルトの名無しさん
08/07/20 18:09:06
「new演算子のオーバーライド」で、どのコンストラクタを呼びたくなるわけ?

ひょっとしてたとえば、メモリ管理クラスがあって、operator new()で
そのメモリ管理クラスをインスタンス化するためにnewしたくなったけど、
メモリ管理クラスのメモリはどうするんだってな話?

850:デフォルトの名無しさん
08/07/21 04:35:49
クラスのメンバ関数が、自分自身をdeleteする処理を行っても
安全なのでしょうか?
つまりdelete this;ってことになるかな。
自分自身が解体された後にメンバ関数からリターンするって何か変ですよねぇ。
しかもdelete this;の後にも処理が続いてたらやばいですよね。

851:デフォルトの名無しさん
08/07/21 06:40:13
>>850
安全。ただしもちろん、それやったあとにそのインスタンスを使っちゃいけない。

たとえばboost::intrusive_ptrみたいに、値に自身の参照カウンタを持たせるスマートポインタの場合、
値となる型に
void Release() { if (!--refCount_) delete this; }
みたいなメンバ関数を用意することになる。

852:デフォルトの名無しさん
08/07/21 06:41:32
規格上どうなってるかは知らないけど、そういうことをやってるライブラリは知ってる。
他のメンバーにアクセスせずにリターンするだけなら問題はないような。

実際どっちのデザインがいいのだろ。
A a = A::createInstance();
a.Free();
A::Free(a);


853:850
08/07/21 06:50:27
レスありがとうございます。
deleteした後に余計なことしなければ、いけるってことですね。

854:デフォルトの名無しさん
08/07/21 16:09:12
現在ublasを使っていて少しつまづいてしまったので教えていただきたいことがあるのですけど
教えていただけないでしょうか?

ある行列を多くの行列演算の和として計算したいのですが、
代入を繰り返すことでおそくなってしまいます。
例えば以下のような例です。
for(i=0;i<100;i++){
MAT1+=some_matrix;
}
some_matrixには毎回べつの行列が計算されてはいります。

expression template でこれを高速可できるということですが、
for文の中で毎回代入していまうとその時点で式が評価されてしまうので遅くなってしまうようです。
式そのものを変数として保持しておくような事はできるのでしょうか?

初歩的な質問ですみませんがどなたかお願いします。

855:デフォルトの名無しさん
08/07/21 16:15:30
autoやdecltypeがあればいいんだがなぁ。

856:デフォルトの名無しさん
08/07/21 16:36:33
draw_mark = rand() % 4 + 1;
draw_digit = rand() % 13 + 1;

if(h) {
printf("%sの%s\n", mark[draw_mark-1], digit[draw_digit-1]);
}
r = total[draw_digit-1];
この文の+1と-1はあってもなくても結果は同じですよね? 気になったので教えてください

857:デフォルトの名無しさん
08/07/21 16:46:49
他の場所で使ってなければ同じ。

858:デフォルトの名無しさん
08/07/21 18:23:52
結果は同じでも、可読性が違う。
乱数の結果が+1してあれば「乱数値を1オリジンに変換している」というニュアンスが伝わるし、
配列のインデックスが-1してあれば「カード番号を0オリジンに変換している」というニュアンスが伝わる。

859:デフォルトの名無しさん
08/07/21 18:34:07
一方、ロシアは0オリジンで乱数値を扱った。

860:デフォルトの名無しさん
08/07/21 18:39:15
>>859
そういう無意味な書き込みして楽しい?
そうかぁ、寂しい青春送っているんだね。

861:デフォルトの名無しさん
08/07/21 18:49:41
>>860
>>860


最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch