これはUsing std::forward on sub fieldsと同様の質問ですが、私の場合は答えがないようです。キャストされた引数にstd :: forwardを使用する
template<class Base, class F>
void visit(Base&&, const F&) {
throw std::bad_cast();
}
template<class Derived, class... Rest, class Base, class F>
void visit(Base&& base, const F& f) {
if (auto *as_derived = dynamic_cast<Derived *>(&base)) {
return f(std::forward<Base>(*as_derived));
} else {
return visit<Rest...>(std::forward<Base>(base), f);
}
}
私の目標は、次のテストケースの作品ということである。
struct Animal {
virtual ~Animal() {}
};
struct Cat : Animal {
void speak() & { puts("meow"); }
void yowl() && { puts("MEOW!"); }
};
struct Dog : Animal {
void speak() & { puts("woof"); }
void yowl() && { puts("WOOF!"); }
};
int main() {
Animal *a = new Cat();
Animal *b = new Dog();
visit<Cat, Dog>(*a, [](auto&& a){ std::forward<decltype(a)>(a).speak(); });
visit<Cat, Dog>(*b, [](auto&& a){ std::forward<decltype(a)>(a).speak(); });
visit<Cat, Dog>(std::move(*a), [](auto&& a){ std::forward<decltype(a)>(a).yowl(); });
visit<Cat, Dog>(std::move(*b), [](auto&& a){ std::forward<decltype(a)>(a).yowl(); });
}
所望の出力: "!MEOW" "ニャー" "横糸" "横糸!"。 speak
とyowl
は仮想ではないことに注意してください。これらは実際にはテンプレートであり、テンプレートは仮想ではないため、これは私の元のコードで必要です。
std::forward<Base>(*as_derived)
は、完璧な転送を可能にするために*as_derived
のref-qualifierとconst-qualifierを単に変更するだけではありません。 タイプを実際にBase&
にキャストし、visit
の全体を突き止める!
は、私はstd::forward
がやりたい何が標準ライブラリ関数はあります - つまり、完璧な-前方std::forward<Base>
から推定されることになるものと一致する*as_derived
にREF-修飾子とのconst修飾子を変更しますか?
標準ライブラリ機能がない場合、私は自分のために「完全な子タイプ」関数をどのように書くことができますか?
上記のWandboxのリンクには、このテストケースで「機能する」ものが含まれていますが、constnessは保持されず、まったく上手く見えません。
これは、すべてのcv-refのものを列挙するよりもずっとうれしいです。 – Barry