Trailing return type of subtraction guide is not a specialization

I am trying to draw the argument of an extended template class using the new C ++ 17 subtraction tutorials. Unfortunately, it looks like you can use simple template declarations after -> , but I need a helper structure to determine the resulting type.

My use is one thing: I have a variational template class that accepts an arbitrary number of different types. For one constructor I want to specify each of them, for another ctor I want to specify only one type and replicate it N times.

To access this N in the output guide, I introduced a new type:

 template<size_t N> struct Replicate { }; 

The class I look like this:

 template<typename... Foos> struct Foo { // [ ... ] member std::tuple<Foos...> // ctor 1: give values for all types (easy to deduce) Foo(Foos&&... args /* rvalue ref, NOT forwarding */) { }; // ctor 2: give one value and N, result is N copies of this value. // takes Replicate<N> as parameter to aid the deduction. template<typename T, size_t N> Foo(const T& t, Replicate<N>) { }; }; 

Usage will look like this:

 Foo f1{1, 2, 3.0}; // deduce Foo<int, int, double>; Foo f2{8, Replicate<4>{}}; // deduce Foo<int, int, int, int>; 

A subtraction guide for the first - directly:

 template<typename... Ts> Foo(Ts&&...) -> Foo<Ts...>; 

This becomes problematic with the second (ctor 2) subtraction guide. First I need a helper structure to create Foo<T, T, ... /* total N times */, T> from T and N

 template<typename, typename, typename> struct ExpandNTimes; template<typename T, size_t... Is> struct ExpandNTimes<T, std::index_sequence<Is...>> { template<size_t> using NthType = T; using Type = Foo<NthType<Is>...>; }; 

Then in the deduction guide, I want to use an assistant to infer the correct type. I can not use Foo<something> directly, since there is no "create a package of parameters in place", so there is a supporting structure.

 template<typename T, size_t N> Foo(const T&, Replicate<N>) -> typename ExpandNTimes<T, std::make_index_sequence<N>>::Type; 

Unfortunately, this leads to an error like this:

 error: trailing return type of 'typename ExpandNTimes<T, /* std things */>::Type' deduction guide is not a specialization of 'Foo<Ts>' 

Is there any way around this problem?

+5
source share
2 answers

This is not possible with the output of the template template argument - both template names should be the same , and the thing after the -> should be simple-template-id . This leaves no room for fraud patterns.

But nothing prevents you from doing what is intended to replace the template template argument: factory function:

 template <typename T, size_t N> typename ExpandNTimes<T, std::make_index_sequence<N>>::Type makeFoo(T const&, Repliace<N>); 
+6
source

This can be done if you can change the definition of Replicate to insert the package into the base class:

 template<class> struct ReplicateBase {}; template<size_t N> struct Replicate : ReplicateBase<std::make_index_sequence<N>> {}; template<size_t, class T> using Meow = T; template<typename T, size_t... Ns> Foo(const T&, ReplicateBase<std::index_sequence<Ns...>>) -> Foo<Meow<Ns, T>...>; 

Then it is a β€œsimple” task to limit everything else so as not to compete with this guide when transferring Replicate :

  • Foo(Foos&&... args) { } and template<typename... Ts> Foo(Ts&&...) -> Foo<Ts...>; (are you sure you want to display links when passing lvalues?) should be limited if Foos / Ts not Replicate s
  • template<typename T, size_t N> Foo(const T& t, Replicate<N>); it must be limited so that it is not used to output an empty package (for example, when sizeof...(Foos) == N )
+1
source

Source: https://habr.com/ru/post/1275977/


All Articles