When does type information flow backwards in C++?

前端 未结 3 1592
栀梦
栀梦 2021-01-29 23:39

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

In

3条回答
  •  执笔经年
    2021-01-29 23:47

    Here is at least one case:

    struct foo {
      template
      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
    struct tag_t {using type=T;};
    
    template
    struct deduce_return_t {
      F f;
      template
      operator T()&&{ return std::forward(f)(tag_t{}); }
    };
    template
    deduce_return_t(F&&)->deduce_return_t;
    
    template
    auto construct_from( Args&&... args ) {
      return deduce_return_t{ [&](auto ret){
        using R=typename decltype(ret)::type;
        return R{ std::forward(args)... };
      }};
    }
    

    so now I can do

    std::vector 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> 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.)

提交回复
热议问题