
テンプレートクラスについていろいろ試していたところ以下のようなコードで
struct A {
struct AA { };
operator A::AA() { return A::AA(); } // (1)
};
template<typename T>
struct B {
struct BB { };
template<typename U>
operator B<U>() { return B<U>(); } // (2)
template<typename U>
operator typename B<U>::BB() { return typename B<U>::BB(); } // (3)
};
int main()
{
static_cast<A::AA>(A()); // (1) ok
static_cast<B<int> >(B<short>()); // (2) ok
static_cast<B<int>::BB>(B<short>()); // (3) compile error
return 0;
}
(1)と(2)はできて(3)だけがコンパイルを通りませんでした。
試したコンパイラはVC9とg++(3.3.4)とbcc32(5.5.1)で、VC9では以下のようなエラーをはきました。
「error C2440: 'static_cast' : 'B<T>' から 'B<T>::BB' に変換できません。
with [ T=short ] and [ T=int ]
コンストラクタはソース型を持てません、またはコンストラクタのオーバーロードの解決があいまいです。」
(1)と(2)ができれば(3)のようなこともできそうな感じがしたのですが、他に書き方があるのでしょうか。
どなたかご存知の方がいらっしゃいましたらご教示お願いします。
No.3ベストアンサー
- 回答日時:
こんにちは。
何度もすんません。struct BBの中にダミーのenumを置いて、operator U()の中に其れを書けば、B<U>::BB以外のキャストをした時にコンパイルエラーを出させる事が出来ました。
此れにて筆を収めさせて頂きます。
struct B
{
struct BB{ enum{IsBB = 0}; };
//B<U>への変換を受け入れる
template<typename U>
operator B<U>(){ return B<U>(); } //(2)
//以下でB<?>::BBである事を保障出来る
template<typename U>
operator typename U()//(3)
{
U::IsBB;//UがBBで無い時、ココでコンパイルエラーに出来る
return typename U();
}
//boolへの変換を受け入れる
operator bool() const { return true; } //(4)
};
static void test(const B<int>::BB&)
{}
int main()
{
static_cast<A::AA>(A());//(1) ok
static_cast<B<int> >(B<short>());//(2) ok
static_cast<B<int>::BB>(B<short>());//(3) ok
static_cast<B<int>::BB>(B<int>());//(3) ok
::test(B<short>());//(3) ok
::test(B<int>());//(3) ok
//以下の3つのキャストは認めてはいけない
static_cast<int>(B<int>()); //(3) error
static_cast<A>(B<char>()); //(3) error
static_cast<A::AA>(B<long>()); //(3) error
if(B<char>())//(4) ok
{
//
}
return 0;
}
御礼が大変遅くなってしまいすみません。
> 何度もすんません。
だなんてとんでもございません。とてもありがたい限りです。
逆に私の方が申し訳ない限りです・・・
なるほど、ちょっと強引かも知れませんがお答えいただいた方法で目的としていた機能は
実現できました。
感激です。ありがとうございます。
・・・でもやっぱり(1)(2)は適合してくれて、なぜ(3)だけ適合してくれないのかが
気になるので質問内容を改めて再投稿してみます。
これまでの非常に丁寧なご回答大変ありがとうございました。
またお付き合いいただけるとうれしいです。
No.4
- 回答日時:
GCC だと「コピーコンストラクタとデフォルトコンストラクタのどっちを使うかわからん」という素敵なエラーなんですよね.... ちょっとこの辺は規格でも探し切れていません.
とりあえず手元の GCC で確認した限りでは
・B<U>::BB に, B<T> を引数にするコンストラクタを作る
・B<T> で B<U>::BB をフレンド宣言する
で逃げられるかもしれない.
この回答への補足
正確にはキャスト自体が目的ではなく(1)のような内部クラスへの型変換演算子と
(2)のような他の引き数を持つテンプレートクラスへの型変換演算子は適合するのに、
その2つを組み合わせた(3)の他の引き数を持つテンプレートクラスの内部クラスへの
型変換演算子は適合しないということがどうにも納得がいかなかったのです。
ちなみに最初のものには書いていませんでしたが
template<class T>
struct B {
struct BB { };
operator typename B<T>::BB() { return typename B<T>::BB(); } // (4)
};
の(4)ように同じ引き数を持つテンプレートクラスの内部クラスへの型変換演算子は
適合してくれました。
なのでどういうルールで適合してくれるのか、わからなくなってしまったのです。
御礼が遅くなってしまい申し訳ございません。
ご回答ありがとうございます。
> B<U>::BB に, B<T> を引数にするコンストラクタを作る
は、おそらく最初に machongola さんにご回答いただいたものだと思うのですが、
違っていたらすみません。あと私の質問内容が悪くてすみません。
もう一度質問内容を改めて再投稿したいと思います。
せっかく回答していただきながら大変申し訳ございません。
No.2
- 回答日時:
こんにちは。
御礼頂きました。其の後、チョッと試したのですが、operator B<U>::BB()とせず、ストレートにoperator U()とすれば適合する様です。
尚(2)(4)(5)が無いと全て(3)が使用されます。要は、operator U()だと何でもかんでも適合してしまいます。
なので、オーバーロードで型の特定を厳密化させて行き、なるべくoperator U()に適合するのを遅延させた方が良さそうです。
後、最後の最後までoperator B<U>::BB()が適合する事はありませんでした。因みにテンプレートx2パラメータを以ってしても不可能でした。
↓コレでも無理
template<template<class>class X, typename U>
operator typename X<U>::BB() { return typename X<U>::BB(); }
//一応出来たので参考程度に
template<typename T>
struct B
{
struct BB{};
template<typename U>
operator B<U>(){ return B<U>(); } // (2)
template<typename U>
operator typename U(){ return typename U(); }// (3)
operator typename B<T>::BB() { return typename B<T>::BB(); }// (4)
operator bool() const { return true; } // (5)
};
static void test(const B<int>::BB&)
{}
int main()
{
static_cast<A::AA>(A());//(1) ok
static_cast<B<int> >(B<short>());//(2) ok
static_cast<B<int>::BB>(B<short>());//(3) ok
static_cast<B<int>::BB>(B<int>());//(4) ok
::test(B<short>());//(3) ok
::test(B<int>());//(4) ok
if(B<char>())//(5) ok
{
//
}
return 0;
}
No.1
- 回答日時:
こんばんは。
(3)には適合しない見たいです。
BBにB<T>の変換コンストラクタを書けばまかり通るようです。でも、何だか怪しい様な・・・。
template<typename T>
struct B
{
struct BB
{
explicit BB(const B<T>& r){}
void TestMethod(){ std::cout<< "test method" << std::endl; }
};
template<typename U>
operator B<U>(){ return B<U>(); } // (2)
//ココは適合しないらしい
//template<typename U>
//operator typename B<U>::BB(){ typename return B<U>::BB(); } // (3)
};
int main()
{
static_cast<A::AA>(A());// (1) ok
static_cast<B<int> >(B<short>());// (2) ok
static_cast<B<int>::BB>(B<short>());// (3) ok
static_cast<B<int>::BB>(B<short>()).TestMethod();// (4) ok
return 0;
}
こんばんは。返事が遅くなりましてすみません。
なるほど内部クラスに変換コンストラクタを書いてあげればいいということですね。
ですがやはり(3)のように型変換演算子のオーバーロードで何とかすることは
できないでしょうか。
というのも STL の auto_ptr の auto_ptr_ref のようなものを内部クラスにして
書くようなことはで出来ないものかと考えていたのです...
せっかくお答えいただいたのに私の説明不足で申し訳ございません。
ですが型変換は出来ることがわかったので大変助かりました。
ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# leetcode 155 minstack 1 2022/05/07 16:43
- C言語・C++・C# int tff(int clk) { static int state = 0; //状態 stat 1 2022/07/11 21:14
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# プログラムが書けません。 4 2023/01/22 22:57
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
「指定されたキャストは有効で...
-
C言語での引数の省略方法
-
#define _CRT_SECURE_NO_WARNIN...
-
int16_t の _t は何?
-
ラップ関数とはどんなものですか?
-
足し算と引き算だけでつくる演算
-
C#の質問
-
【至急】プログラムにエラーが...
-
C++の関数をCで呼ぶには??
-
systemの戻り値を取得する方法
-
C言語初心者です、、、お助けく...
-
複数桁10進数の*桁目だけを抽出...
-
if と配列の組み合わせ
-
PowerShellがうまくいかない
-
C言語の基礎 . 2乗値の差につ...
-
C#で配列の分割
-
桁あふれ誤差のプログラムで質...
-
scanfの無限ループ
-
【C++】関数ポインタの使い方
-
ファイルの読み込み
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「指定されたキャストは有効で...
-
C言語での引数の省略方法
-
複数桁10進数の*桁目だけを抽出...
-
C言語 エラーの原因がわからな...
-
#define _CRT_SECURE_NO_WARNIN...
-
ラップ関数とはどんなものですか?
-
【C++】関数ポインタの使い方
-
実数の整数部,小数部の取得
-
int型の変数値をバイト列として...
-
std::set<int> で、ある値が何...
-
PowerShellがうまくいかない
-
(int *)の意味
-
CStringの配列要素を関数で受け...
-
ColorをRGBで指定する方法
-
「{ } で囲むだけ」は正しい?
-
acceptをalarmでタイムアウトさ...
-
if と配列の組み合わせ
-
read関数をノンブロッキングで...
-
(マルチスレッド)_beginthrea...
-
int16_t の _t は何?
おすすめ情報