2

背景:多くの関数型言語は代数データ型をサポートしており、仮想関数と継承である程度エミュレートできます。

派生型のサイズが異なるため、最も明白な解決策はヒープの割り当てです。ただし、ユニオンを使用して、追加の割り当てなしでスタック上の最大の型を保持できるはずです。これには、ベースへの追加のポインターを共用体と共に格納する必要があり、同時にコピーと代入が複雑になります。

アクティブなユニオン メンバーを指すユニオンの先頭からのオフセットとしてメンバー セレクターを格納することにより、後者の問題を解決することは非常に重要です。C++には、各メンバーへのポインターが異なる型を持つことを除いて、目的にほぼ適合しているように見えるメンバーポインターがあります。

質問: Derived T::* を Base T::* にキャストできないのはなぜですか?

上記とは関係のない、同じ制限にぶつかるおもちゃの例を次に示します。

struct fish {};
struct shark : public fish {};
struct trout : public fish {};

struct aquarium
{
    shark shark;
    trout trout;
};

fish aquarium::* pick_dinner(bool dangerous = true)
{
    if (dangerous)
    {
        return &aquarium::shark;
    }
    return &aquarium::trout;
}

#include <iostream>

void cook(fish&)
{
    std::cerr << "Do it yourself\n";
}

int main()
{
    aquarium spherical, hexagonal;
    fish aquarium::*ingredient = pick_dinner();
    cook(spherical.*ingredient);
    cook(hexagonal.*ingredient);
}

生成されたコンパイル エラー:

main.cpp:15:16: error: cannot initialize return object of type 'fish aquarium::*' with an rvalue of type 'shark aquarium::*'
        return &aquarium::shark;
               ^~~~~~~~~~~~~~~~
main.cpp:17:12: error: cannot initialize return object of type 'fish aquarium::*' with an rvalue of type 'trout aquarium::*'
    return &aquarium::trout;
           ^~~~~~~~~~~~~~~~
2 errors generated.
4

1 に答える 1

4

へのキャストが許可されていないのはなぜDerived T::*ですかBase T::*?

言語標準で許可されていないためです。null メンバ ポインタの変換を除いて、許可されている唯一のポインタからメンバへの変換は、標準部分で述べられているように、型cv T Base::*から への変換です。cv T Derived::*4.11/2

正確な理由はわかりませんが、対応するコア言語の問題 794は、「標準化プロセスのこの時点でこの変更を行うというコンセンサスがない」ため拒否されました。この問題に関する最近の活動は、次の C++ 標準 (C++17) で変更される可能性があることを示しています。

于 2014-10-13T11:54:25.710 に答える