3

Is there a way to use something like :

constexpr auto foo = hana::make_tuple(hana::type_c<Foo1>,hana::type_c<Foo2>);

with something like:

template < typename ... Ts >
struct Final {

  constexpr Final(Ts && ... args) {}
};

hana::unpack(foo, [] (auto && ... args) { return Final(args...); });

Because with that code, unpack can't deduce lambda/function type. Basically I want to create a type which takes a list of arguments but I have a tuple which contains the arguments.

Barry
  • 286,269
  • 29
  • 621
  • 977
Mathieu Van Nevel
  • 1,428
  • 1
  • 10
  • 26
  • That code isn't valid C++14 or C++17. Are you using Concepts? – Kerrek SB Apr 22 '17 at 16:04
  • @KerrekSB I don't need concepts here, could you tell me why it's invalid please? – Mathieu Van Nevel Apr 22 '17 at 16:08
  • `auto` is not a valid function parameter type in C++. It's only allowed in lambda expressions. – Kerrek SB Apr 22 '17 at 16:09
  • @KerrekSB Oh I remenber clang couldn't do it, but with gcc 7 I can. Not something official? The constructor was my error thought. – Mathieu Van Nevel Apr 22 '17 at 16:10
  • 1
    `auto` is a function parameter type is part of the Concepts TS (`-fconcepts`). – Kerrek SB Apr 22 '17 at 16:26
  • this is allowed in -std=gnu++11 on ubuntu, and auto as parameter should be possible in C++17 with following compiler setting on windows: /Zc:auto- However, it still is not really working - @Kerrek SB, perhaps you could elaborate on the usage of -fconcepts – serup Sep 26 '17 at 13:38
  • 1
    @serup in fact auto will work if your compiler started to implement Concepts TS. You don't need to specifies any std with gcc, even -fconcept isn't needed. – Mathieu Van Nevel Sep 28 '17 at 18:24

2 Answers2

4

The problem is in your lambda:

[](auto && ... args){ return Final(args...); }
//                          ~~~~~~~

Final isn't a type, it's a class template. As such, you need to explicitly provide the types. Something like:

[](auto&&... args){ return Final<decltype(args)...>(
    std::forward<decltype(args)>(args)...); }

In C++17, with template deduction for class template parameters, the Ts&& does not function as a forwarding reference (see related answer), so the implicit deduction guide would not match your usage anyway as you are only providing lvalues and the guide requires revalues. But this would work:

[](auto... args){ return Final(std::move(args)...); }
Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    Perhaps it would be better if the constructor took the Ts by value and did the `std::move` there instead of in the lambda. – Jason Rice Apr 22 '17 at 16:50
  • I think it should be `Final` in the second code snippet for perfect forwarding (--mind the `&&`). – davidhigh Mar 14 '20 at 00:40
  • @davidhigh They mean the same thing - `decltype(args)` is always a reference here. – Barry Mar 14 '20 at 01:18
  • "Here" means in the context of the OP, I guess, where a local variable `foo` is `unpack`'ed. But this doesn't hold in general, if I get it correctly, because `args` could be an rvalue ref but `decltype(args)` is deduced as lvalue ref. – davidhigh Mar 14 '20 at 01:33
  • @davidhigh Here meant in the place you were suggesting to change. – Barry Mar 14 '20 at 03:32
1

If I understand your question correctly, what you're actually looking for is

template <typename ...Ts>
struct Final { ... };

constexpr auto foo = hana::make_tuple(hana::type_c<Foo1>,hana::type_c<Foo2>);
auto final_type = hana::unpack(foo, [](auto ...args) {
  return Final<typename decltype(args)::type...>;
});
// now, final_type is a hana::type<Final<Foo1, Foo2>>

You can also achieve the same thing using hana::template_:

constexpr auto foo = hana::make_tuple(hana::type_c<Foo1>,hana::type_c<Foo2>);
auto final_type = hana::unpack(foo, hana::template_<Final>);

The problem I see with Barry's answer is that you'll end up creating a Final<decltype(hana::type_c<Foo1>), decltype(hana::type_c<Foo2>)>, which is probably not what you want.

Louis Dionne
  • 3,104
  • 1
  • 15
  • 35
  • I think that you was influenced by my previous questions, because my goal is not to create a final type with a tuple of type. If you want more context, I was working with Jason Rice solution here : https://stackoverflow.com/questions/43089587/change-runtime-research-for-a-compile-time-one and I wanted to join several multi_map. Or maybe I just misunderstood your answer sorry ^^" – Mathieu Van Nevel Apr 23 '17 at 19:47
  • No worries. All I'm saying is that with Barry's solution, if you do `unpack(foo, the-lambda-he-provided)`, you end up with `Foo, type>`, which seems a little bit strange. In any case, I'm glad Barry's solution solves your problem. – Louis Dionne Apr 24 '17 at 01:22
  • Ah, that's right. Barry's answer doesn't address the fact that the OP `foo` is a tuple of `hana::type`. – Jason Rice Apr 24 '17 at 17:22