When does type information flow backwards in C++?

  • A+

I just watched Stephan T. Lavavej talk at CppCon 2018 on "Class Template Argument Deduction", where at some point he incidentally says:

In C++ type information almost never flows backwards ... I had to say "almost" because there's one or two cases, possibly more but very few.

Despite I tried to figure out which cases he might be referring to, I couldn't come up with anything and hence the question:

In which cases the C++17 standard mandates that type information propagate backwards?


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


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: