次のものをC++でコンパイルできるのはなぜですか?
#include<iostream>
using namespace std;
class mytest
{
public:
operator int()
{
return 10;
}
operator const int()
{
return 5;
}
};
int main()
{
mytest mt;
//int x = mt; //ERROR ambigious
//const int x = mt; //ERROR ambigious
}
使用すると常にあいまいさが生じるのに、変換演算子の異なるバージョン(定数に基づいて)をコンパイルできるのはなぜ意味があるのですか?
誰かが私がここで欠けているものを明確にすることはできますか?
戻り値の定数だけが異なる会話演算子を書くことは明示的に許可されていないという結論に達します。コンパイルプロセスで明示的に禁止するのは高すぎるです。
戻り値の型のみが異なる(メンバー)関数を忘れないでください
class mytest
{
int f();
const int f();
};
禁止されています:
エラー:「const int mytest :: f()」はオーバーロードできません
違いを生むのは、変換演算子がoperator
で始まるだけです。
変換のために、それらはあいまいです。ただし、明示的に呼び出すこともできます。例えば.
int x = mt.operator int();
const int x = mt.operator const int();
厳密な意味では、const
にとってあまり意味をなさないとしても、これは正当なことだと思います。
関数の宣言と関数の型には違いがあり、同じ制約はありません。
関数declarationsは、戻り値の型または(C++ 17以降の)例外仕様のみが異なる場合があります。ただし、関数typeについてはそのようなことは言われていません(私の知る限り)。
標準の[class.conv.fct]は、変換関数を、そのような形式(3つの選択肢がリストされている)として記述しています。これらはすべて、通常の関数宣言のようには見えません。
does state、関数タイプは"関数はパラメータを取得せずにconversion-type-idを返します"しかし、変換関数declarationsが戻り型のようなものを持っていることはどこにも言及されていません。それどころか、リストされた3つの代替形式には非常に明確に戻りタイプがありません。
変換関数はhave戻り値の型(宣言内の...)ではないため、競合することはできません。だから、私は、最も厳格で、最も退屈な意味で、それが理にかなっているかどうかにかかわらず、「合法」でさえあると思います。
あなたがそれについて考えるなら、それはどういうわけかも法的であるでなければなりません。クラスには、異なるものへの複数の変換関数があります(const
だけではありません)。そのようなコードは存在しますが、そのように進むことは非常に意味があります。
たとえば、File
(ファイル名)またはhandle_t
(オペレーティングシステムハンドル)に変換するクラスstring
がありますラッパークラスが直接サポートしていないOS固有の関数またはエキゾチックな関数を使用したい(writev
、tee
、またはepoll
を考えてみてください)働くことを期待してください!
ただし、変換関数を「単なる関数」として扱った場合、戻り値の型のみが異なり、宣言が違法になります。だから...それはうまくいきません。
使用すると常に曖昧さが生じる場合、変換演算子の異なるバージョン(定数に基づいて)を許可するのが理にかなっています(コンパイルされる)。
(高度に人工的なユースケースを除いて)通常は意味がなく、コンパイラはそれについて警告することができます。
prog.cc:12:25: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
operator const int()
^