1. ホーム
  2. c++

[解決済み] C++で型情報が逆流するのはどんなときか?

2023-02-27 20:17:25

質問

での Stephan T. Lavavej の講演を見たところです。 CppCon 2018 で、quot;Class Template Argument Deduction" について話しました。 ある点 で、彼はついでにこう言っている。

C++では、型情報はほとんど後方には流れない. というのも、1つか2つのケースがあり、もっとあるかもしれませんが、非常に少ないからです。 .

どのようなケースを指しているのか、考えてみたのですが、何も出てきませんでした。そこで質問です。

C++17 標準では、どのような場合に型情報が後方に伝搬することを義務付けていますか?

どのように解決するのですか?

少なくとも1つのケースを紹介します。

struct foo {
  template<class T>
  operator T() const {
    std::cout << sizeof(T) << "\n";
    return {};
  }
};

とすれば foo f; int x = f; double y = f; とすると、型情報が逆流し、何が T の中にある operator T .

もっと高度な使い方ができます。

template<class T>
struct tag_t {using type=T;};

template<class F>
struct deduce_return_t {
  F f;
  template<class T>
  operator T()&&{ return std::forward<F>(f)(tag_t<T>{}); }
};
template<class F>
deduce_return_t(F&&)->deduce_return_t<F>;

template<class...Args>
auto construct_from( Args&&... args ) {
  return deduce_return_t{ [&](auto ret){
    using R=typename decltype(ret)::type;
    return R{ std::forward<Args>(args)... };
  }};
}

で、これで

std::vector<int> v = construct_from( 1, 2, 3 );

で、動作します。

もちろん、なぜ {1,2,3} ? まあ {1,2,3} は式ではありません。

std::vector<std::vector<int>> v;
v.emplace_back( construct_from(1,2,3) );

のように、確かに、もう少し巧妙な操作が必要です。 ライブの例 . (私は、deduce returnにFのSFINAEチェックをさせ、FをSFINAE friendlyにする必要があります。 deduce_return_t 演算子 T で std::initializer_list をブロックしなければなりません)。