【C++】template 統合スレ -- Part5
>>927 どーも。
期待通り?VC7.1でもエラーになってくれました。
(template argはfriend指定できないみたい)
class Enemy
{
friend class Friend;//secretに必要
template <class T,class L>struct Connection :public L
{
friend class Friend;//testに必要 ->VC7.1はこっちだけでもOKだった...orz
C++Primer第3版日本語版P865〜866
クラステンプレートにおけるfriend宣言を見ると、
テンプレート・パラメータはfriendクラスそのものには使えないが、friendクラス
のテンプレート・パラメータの方を指定する事ができる。
例
template <typename T>
class Foo {
//いろいろ
};
template <typename T>
class A {
friend class Foo<T>;
};
>>928 そこでboostですよ。
#include <boost/mpl/identity.hpp>
template <class T>struct Connection
{
typedef typename T::type X;
friend X;
private:
static void test()
{std::cout << typeid(X).name() << ":" << typeid(Connection).name()<< std::endl;}
};
struct Friend :public Connection< boost::mpl::identity<Friend> >
{
using Connection< boost::mpl::identity<Friend> >::test;
};
>>929,930
ありがとうございました。関数の方はVC7.1とGCC3.4.3でOKでした。
class Friend_Tag;
template <class T,class L>struct Connection;
template <typename T>class Friend;
class Enemy
{
friend class Friend<Friend_Tag>;//GCCの場合必須
static void secret(){ std::cout << "secret!!" << std::endl; }
static const int secret_data = 1000000;
};
template <class T,class L>struct Connection :public L
{
/*C++Primer第3版日本語版P865〜866
クラステンプレートにおけるfriend宣言を見ると、
テンプレート・パラメータはfriendクラスそのものには使えないが、friendクラス
のテンプレート・パラメータの方を指定する事ができる。*/
friend class Friend<T>;
typedef Connection<T,L> connect_type;
private:static void test()
{std::cout << typeid(T).name() << ":" << typeid(Connection).name()<< std::endl;}
static const int test_data = 100000;
};
class Friend_Tag{};//friendクラスのテンプレート・パラメータの方を指定
template <typename T=Friend_Tag>class Friend :public Connection<T,Enemy>
{public:
using connect_type::test; //friend経由でusingする
using connect_type::secret;//friend経由でusingする
//using connect_type::test_data; //friend経由でusingする GCC3.4.3(OK) VC7.1(NG)
//using connect_type::secret_data;//friend経由でusingする GCC3.4.3(OK) VC7.1(NG)
};
>>931 君にはC++Templatesをお勧めしよう。
大きな声では言えないが、CHMやPDFはよく探せばどこにでも落ちている。
俺は画面で見るのが嫌なのでAMAZONで買ったが。
しかしこんな名著がなぜ日本語訳化されないのか不思議。
>>933 まだだけど内容が偏ってそうなタイトルだな。
936 :
936:04/11/18 14:05:19
std::string a(){ return ""; }
int b(){ return 0; }
template< void (*pf)() >
struct A
{ static const int id=0; };
template< class R, R (*pf)() >
struct A<pf>
{ static const int id=1; };
int main()
{
std::cout << A< &a >::id << std::endl;
std::cout << A< &b >::id << std::endl;
return 0;
}
error C2764: 'R' : テンプレート パラメータは部分的特殊化 'A<pf>' では使用されません。
main内をいじくらずにコンパイルをとおすにはどうしたらいいですか?
>>936のコードをBCCでやろうとしたらできちゃった。
これじゃ俺には答えられん。OTL
>>936 お前がやりたいのはこれか?
template <typename FP>
struct A;
template <typename R>
struct A<R (*)()>
{enum{id = 0};};
template <>
struct A<void (*)()>
{enum{id = 1};};
>>938 936さんは外部リンケージのある関数ポインタをテンプレートの
非型パラメータに取りたいんでしょう.
>>936 ですか?
そのコードはprimary templateとその特殊化で非型パラメータの型が異っていて
(void (*)()とR (*)()),そういう特殊化は許されないです.
なのでmain関数をいじらずにそれを通すのは無理と思います.
見たところ,関数ポインタからその戻り値がvoidかどうかを判別する静的整数値が
欲しいと見受けられますが,その解釈で良いですか?
STLPortってシリアライズ対応してるんですか?
みあたらないのですが・・・・・
>>939 やりたいことは関数ポインタを非型パラメータとして渡し戻り値の型をresult_tとかで取得できるようにしたいです
以下のソースでとりあえず関数ポインタを単独で渡すことに成功して、いけるかとおもったのですが全部null_tですた
試しに非型パラメータ経由で呼び出したらおちますたorz
template<class T>struct aaa{};
int a(){return 0;}
std::string b(){return "";}
aaa<int> c() { return aaa<int>(); }
struct null_t{};
template<void *p,class R=null_t>struct A
{
typedef null_t result_t;
static const id = 0;
};
template<class R, R (*const pf)()>struct A< pf, R >
{
typedef R result_t;
static const id = 1;
test(){ (*pf)(); }
};
int main()
{
std::cout << typeid(A<&a>::result_t).name() << " " << A<&a>::id << std::endl;
std::cout << typeid(A<&b>::result_t).name() << " " << A<&b>::id << std::endl;
std::cout << typeid(A<&c>::result_t).name() << " " << A<&c>::id << std::endl;
A<&a> a; A<&b> b; A<&c> c;
return 0;
}
>>941 それは無理。
typeofが使える環境ならいいけど。
gcc3.2 3.3 3.4 以降 の libstdc++ と、STLportでは、どっち使ってます?
gcc も version 3から、c++ 対応が強化されてますし。
http://boost.sourceforge.net/regression-logs/ みても、stlport は、いらないかと。
VC がないんだけど、前はあったような気がするのだが。
VC7.1 の場合も標準準拠具合は進んでるし、STLport いらないかも?
でもSTLport のほうが速いのかな。
STLPortのデバッグモードがいいよ
>941
942さんの言うようにその要求はまさにtypeofの機能なので厳しいでしょう.
戻り値がvoidかそうでないか等のように,オブジェクトのある程度の種別を
識別するコンパイル時定数を得ることなら以下の手法で出来ますが・・・.
#include <iostream>
struct yes_t{ };
struct no_t{ yes_t padding[256]; };
template<class T> no_t is_void_ret(T (*)());
yes_t is_void_ret(void (*)());
#define IS_VOID_RET(pf) (sizeof(is_void_ret(pf)) == sizeof(yes_t))
void f(){ };
int g(){ return 0; }
int main()
{
std::cout << IS_VOID_RET(&f) << std::endl;
std::cout << IS_VOID_RET(&g) << std::endl;
}
ちなみにこの手法の究極形が,既存のC++の文法のみでtypeofを実現するってヤツなんですけどね.
boost1.32.0キタ━━━━(゚∀゚)━━━━!!
boost1.32.0やっとキタ━━━━(゚∀゚)━━━━!!
おまえら気づくのおせーよw
タグは打たれないのかい?
すみません、質問があります。
boostのファンクタを使ってみようと思っているのですが、
脳がこんがらがってきました。
boost::shared_ptr< hoge > pointer;
というポインタと、
std::list< boost::weak_ptr< hoge > > container;
というコンテナがあり、
コンテナの中からremove_if()でpointerと同じ値を削除したいのです。
ところが、コンテナの中身がweak_ptrなので、一度lock()しないといけません。
こういう場合、どういうファンクタを書けばいいのでしょうか?
出来ればlambdaを使わず(怖すぎ)、bindやmem_fnだけで書く方法を
教えていただけないでしょうか。
誰か答えろよ。
頭がこんがらがるようなことはやらないが吉。
954 :
デフォルトの名無しさん:04/11/22 14:56:58
誰だよ昨晩から上げ荒らしをしているばかは。一応通報したからね。
>>952 解っているがおまえの態度が気に入らない。
boost lambda で再帰ってどう書けばいいのかな?
>>958 試してないけどboost::functionも使ってこんな感じで行けない?
function<int (int)> f= ret<int>(if_(_1==0)[1].else_[_1*f(_1-1)]);
cout<< f(5)<< endl;
boostの悪い使い方の典型だな
962 :
958:04/11/24 17:50:36
>>960 function<int (int)> f= ret<int>
(if_then_else_return(_1==1,1,_1*f(_1-1)));
とかもやってみたけど駄目みたい。(再帰はムリなのかもしれぬ...
ここまでしてlambda使いたいか?て思う
半年ぐらいC++から離れたら読めなくならない?
>>962 fの呼び出しはbindで包まないとだめだと思うが。
俺の環境ではif_then_elseが使えないから、
function<int (int)> f= bind<int>(var(f), _1);
で、スタックオーバーフローを確認した。
main() {
int (*tarai)();
tarai = lambda(x,y,z) {
if (x <= y) return y;
else return tarai(
tarai(x - 1, y, z),
tarai(y - 1, z, x),
tarai(z - 1, x, y));
};
(lambda(x,y,z){ printf("tarai => %d\n",tarai(x,y,z)); })(12,6,0);
}
これをboostで書き直すとどうなるの?
>>965 #include <cstdio>
#include "boost/function.hpp"
#include "boost/lambda/lambda.hpp"
#include "boost/lambda/bind.hpp"
#include "boost/lambda/if.hpp"
#include "boost/bind/protect.hpp"
#include "boost/ref.hpp"
int main()
{
boost::function<int (int,int,int)> tarai;
using namespace boost::lambda;
using boost::protect;
using boost::ref;
tarai =
if_then_else_return((_1 <= _2)
, ret<int>(_2)
, bind(ref(tarai)
, (protect(bind(ref(tarai), _1 - 1, _2, _3)))(_1,_2,_3)
, (protect(bind(ref(tarai), _2 - 1, _3, _1)))(_1,_2,_3)
, (protect(bind(ref(tarai), _3 - 1, _1, _2)))(_1,_2,_3)
)
);
std::printf("tarai => %d\n", tarai(12,6,0));
}
マジでboostからlambdaはずして欲しい。
俺が使わなくても他のやつが使うじゃん。
俺そんなの読むのヤだよ。
って実際lambda使ってるやつ見たことないけど。
勝手だなぁw
lambda を馬鹿みたいに多用する奴がアホなだけだからなま暖かく見守っとけば?
boost自体がお遊びでしょ
boost見てると
「でっきる〜かな、でっきる〜かな♪」
と聞こえてくるんですが。
ほんとうに聞こえてくるなら病院に行ったほうがいいかと。
C++にlambdaがないのがいけないんだよ。
Perlにすらあるのに。
lambdaは予約語だからな。使わないようにしておかないと。