When does type information flow backwards in C++?

Here is at least one case:

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

if you do foo f; int x = f; double y = f;, type information will flow “backwards” to figure out what T is in operator T.

You can use this in a more advanced way:

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)... };
  }};
}

so now I can do

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

and it works.

Of course, why not just do {1,2,3}? Well, {1,2,3} isn’t an expression.

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

which, admittedly, require a bit more wizardry: Live example. (I have to make the deduce return do a SFINAE check of F, then make the F be SFINAE friendly, and I have to block std::initializer_list in deduce_return_t operator T.)

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)