web-dev-qa-db-ja.com

intとconst intで異なる変換関数が使用できるのはなぜですか?

次のものを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
}

使用すると常にあいまいさが生じるのに、変換演算子の異なるバージョン(定数に基づいて)をコンパイルできるのはなぜ意味があるのですか?

誰かが私がここで欠けているものを明確にすることはできますか?

25
code707

戻り値の定数だけが異なる会話演算子を書くことは明示的に許可されていないという結論に達します。コンパイルプロセスで明示的に禁止するのは高すぎるです。

戻り値の型のみが異なる(メンバー)関数を忘れないでください

class mytest
{
    int f();
    const int f();
};

禁止されています:

エラー:「const int mytest :: f()」はオーバーロードできません

違いを生むのは、変換演算子がoperatorで始まるだけです。

1
Wolf

変換のために、それらはあいまいです。ただし、明示的に呼び出すこともできます。例えば.

int x = mt.operator int();
const int x = mt.operator const int();
18
songyuanyao

厳密な意味では、constにとってあまり意味をなさないとしても、これは正当なことだと思います。

関数の宣言と関数の型には違いがあり、同じ制約はありません。

関数declarationsは、戻り値の型または(C++ 17以降の)例外仕様のみが異なる場合があります。ただし、関数typeについてはそのようなことは言われていません(私の知る限り)。

標準の[class.conv.fct]は、変換関数を、そのような形式(3つの選択肢がリストされている)として記述しています。これらはすべて、通常の関数宣言のようには見えません。

does state、関数タイプは"関数はパラメータを取得せずにconversion-type-idを返します"しかし、変換関数declarationsが戻り型のようなものを持っていることはどこにも言及されていません。それどころか、リストされた3つの代替形式には非常に明確に戻りタイプがありません。

変換関数はhave戻り値の型(宣言内の...)ではないため、競合することはできません。だから、私は、最も厳格で、最も退屈な意味で、それが理にかなっているかどうかにかかわらず、「合法」でさえあると思います。

あなたがそれについて考えるなら、それはどういうわけかも法的であるでなければなりません。クラスには、異なるものへの複数の変換関数があります(constだけではありません)。そのようなコードは存在しますが、そのように進むことは非常に意味があります。
たとえば、File(ファイル名)またはhandle_t(オペレーティングシステムハンドル)に変換するクラスstringがありますラッパークラスが直接サポートしていないOS固有の関数またはエキゾチックな関数を使用したい(writevtee、またはepollを考えてみてください)働くことを期待してください!
ただし、変換関数を「単なる関数」として扱った場合、戻り値の型のみが異なり、宣言が違法になります。だから...それはうまくいきません。

5
Damon

使用すると常に曖昧さが生じる場合、変換演算子の異なるバージョン(定数に基づいて)を許可するのが理にかなっています(コンパイルされる)。

(高度に人工的なユースケースを除いて)通常は意味がなく、コンパイラはそれについて警告することができます。

prog.cc:12:25: warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
     operator  const int()
                         ^
4
Jodocus