How to unroll a parameter pack from right to leftC++ template partial specialization: Why cant I match the last type in variadic-template?Partial template specialization with multiple template parameter packsWhy won't template parameter pack be deduced to multiple type arguments in function call?Clang vs GCC - Variadic template parameter pack followed by parameter with default value works in GCC 4.8 but not Clang 3.5Generating template specializations through template metaprogramming. Odd compiler behaviourHow to access first parameter in parameter pack?Can outer parameter pack be expanded with inner parameter pack to be deduced?Size of parameter pack in template specializationC++ template partial specialization: Why cant I match the last type in variadic-template?variadic vs non variadic function template overloading partial orderingFunction template overload resolution with two parameter packs

Classification of surfaces

Pre-plastic human skin alternative

On The Origin of Dissonant Chords

What happened to Captain America in Endgame?

a sore throat vs a strep throat vs strep throat

How to display Aura JS Errors Lightning Out

How much cash can I safely carry into the USA and avoid civil forfeiture?

Apply MapThread to all but one variable

Rivers without rain

Should the Death Curse affect an undead PC in the Tomb of Annihilation adventure?

555 timer FM transmitter

Aligning equation numbers vertically

How to denote matrix elements succinctly?

Is Diceware more secure than a long passphrase?

A ​Note ​on ​N!

Can someone publish a story that happened to you?

Re-entry to Germany after vacation using blue card

Is there a way to generate a list of distinct numbers such that no two subsets ever have an equal sum?

"Whatever a Russian does, they end up making the Kalashnikov gun"? Are there any similar proverbs in English?

What are the steps to solving this definite integral?

Can an Area of Effect spell cast outside a Prismatic Wall extend inside it?

Implications of cigar-shaped bodies having rings?

Minor Revision with suggestion of an alternative proof by reviewer

Two field separators (colon and space) in awk



How to unroll a parameter pack from right to left


C++ template partial specialization: Why cant I match the last type in variadic-template?Partial template specialization with multiple template parameter packsWhy won't template parameter pack be deduced to multiple type arguments in function call?Clang vs GCC - Variadic template parameter pack followed by parameter with default value works in GCC 4.8 but not Clang 3.5Generating template specializations through template metaprogramming. Odd compiler behaviourHow to access first parameter in parameter pack?Can outer parameter pack be expanded with inner parameter pack to be deduced?Size of parameter pack in template specializationC++ template partial specialization: Why cant I match the last type in variadic-template?variadic vs non variadic function template overloading partial orderingFunction template overload resolution with two parameter packs






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








11















I am trying to do a parameter pack unrolling by dispatching to a class recursively. I'd like to do that from right to left since some of the operations do pre-pending.



template <typename... T>
class Foo;

template <typename T>
class Foo<T> /* base case implementation*/;

template <typename T, typename R, typename... Rs>
class Foo<T, Rs..., R>
private:
Foo<T, Rs...> foo_;



Unfortunately, the above gets me:



class template partial specialization contains template parameters that cannot be deduced;
this partial specialization will never be used


This seems odd to me, I would assume that even though the arguments has switched order, Foo<T, Rs..., R> should still match the template specialization.



I've looked at some similar questions:



Specifically, C++ template partial specialization: Why cant I match the last type in variadic-template?



However, the highest voted (non-accepted) answer doesn't make sense to me. Sure I understand that the template parameter pack declaration must be the last in the declaration, but I do that for the template specialization.



I'm not sure why the compiler cannot map Foo<T, Rs..., R> to the initial template declaration Foo<T...> and enforces the parameter pack declaration order there.



Other answers on that thread offer how to extract the last value, but that still doesn't allow you to do recursive parameter pack unrolling, which is sort of the whole point here. Is it just impossible to unroll a parameter pack from right to left?










share|improve this question



















  • 2





    Well you can revert the order of the argument then unroll left to right. You may look an implementation of revert here : bitbucket.org/MartinMorterol/glp/src/dev/include/… or here github.com/edouarda/brigand/blob/master/include/brigand/…

    – Martin Morterol
    Apr 19 at 12:53


















11















I am trying to do a parameter pack unrolling by dispatching to a class recursively. I'd like to do that from right to left since some of the operations do pre-pending.



template <typename... T>
class Foo;

template <typename T>
class Foo<T> /* base case implementation*/;

template <typename T, typename R, typename... Rs>
class Foo<T, Rs..., R>
private:
Foo<T, Rs...> foo_;



Unfortunately, the above gets me:



class template partial specialization contains template parameters that cannot be deduced;
this partial specialization will never be used


This seems odd to me, I would assume that even though the arguments has switched order, Foo<T, Rs..., R> should still match the template specialization.



I've looked at some similar questions:



Specifically, C++ template partial specialization: Why cant I match the last type in variadic-template?



However, the highest voted (non-accepted) answer doesn't make sense to me. Sure I understand that the template parameter pack declaration must be the last in the declaration, but I do that for the template specialization.



I'm not sure why the compiler cannot map Foo<T, Rs..., R> to the initial template declaration Foo<T...> and enforces the parameter pack declaration order there.



Other answers on that thread offer how to extract the last value, but that still doesn't allow you to do recursive parameter pack unrolling, which is sort of the whole point here. Is it just impossible to unroll a parameter pack from right to left?










share|improve this question



















  • 2





    Well you can revert the order of the argument then unroll left to right. You may look an implementation of revert here : bitbucket.org/MartinMorterol/glp/src/dev/include/… or here github.com/edouarda/brigand/blob/master/include/brigand/…

    – Martin Morterol
    Apr 19 at 12:53














11












11








11


6






I am trying to do a parameter pack unrolling by dispatching to a class recursively. I'd like to do that from right to left since some of the operations do pre-pending.



template <typename... T>
class Foo;

template <typename T>
class Foo<T> /* base case implementation*/;

template <typename T, typename R, typename... Rs>
class Foo<T, Rs..., R>
private:
Foo<T, Rs...> foo_;



Unfortunately, the above gets me:



class template partial specialization contains template parameters that cannot be deduced;
this partial specialization will never be used


This seems odd to me, I would assume that even though the arguments has switched order, Foo<T, Rs..., R> should still match the template specialization.



I've looked at some similar questions:



Specifically, C++ template partial specialization: Why cant I match the last type in variadic-template?



However, the highest voted (non-accepted) answer doesn't make sense to me. Sure I understand that the template parameter pack declaration must be the last in the declaration, but I do that for the template specialization.



I'm not sure why the compiler cannot map Foo<T, Rs..., R> to the initial template declaration Foo<T...> and enforces the parameter pack declaration order there.



Other answers on that thread offer how to extract the last value, but that still doesn't allow you to do recursive parameter pack unrolling, which is sort of the whole point here. Is it just impossible to unroll a parameter pack from right to left?










share|improve this question
















I am trying to do a parameter pack unrolling by dispatching to a class recursively. I'd like to do that from right to left since some of the operations do pre-pending.



template <typename... T>
class Foo;

template <typename T>
class Foo<T> /* base case implementation*/;

template <typename T, typename R, typename... Rs>
class Foo<T, Rs..., R>
private:
Foo<T, Rs...> foo_;



Unfortunately, the above gets me:



class template partial specialization contains template parameters that cannot be deduced;
this partial specialization will never be used


This seems odd to me, I would assume that even though the arguments has switched order, Foo<T, Rs..., R> should still match the template specialization.



I've looked at some similar questions:



Specifically, C++ template partial specialization: Why cant I match the last type in variadic-template?



However, the highest voted (non-accepted) answer doesn't make sense to me. Sure I understand that the template parameter pack declaration must be the last in the declaration, but I do that for the template specialization.



I'm not sure why the compiler cannot map Foo<T, Rs..., R> to the initial template declaration Foo<T...> and enforces the parameter pack declaration order there.



Other answers on that thread offer how to extract the last value, but that still doesn't allow you to do recursive parameter pack unrolling, which is sort of the whole point here. Is it just impossible to unroll a parameter pack from right to left?







c++ c++11






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 19 at 13:24









Bob__

5,30831527




5,30831527










asked Apr 19 at 12:47









IdeaHatIdeaHat

5,7581341




5,7581341







  • 2





    Well you can revert the order of the argument then unroll left to right. You may look an implementation of revert here : bitbucket.org/MartinMorterol/glp/src/dev/include/… or here github.com/edouarda/brigand/blob/master/include/brigand/…

    – Martin Morterol
    Apr 19 at 12:53













  • 2





    Well you can revert the order of the argument then unroll left to right. You may look an implementation of revert here : bitbucket.org/MartinMorterol/glp/src/dev/include/… or here github.com/edouarda/brigand/blob/master/include/brigand/…

    – Martin Morterol
    Apr 19 at 12:53








2




2





Well you can revert the order of the argument then unroll left to right. You may look an implementation of revert here : bitbucket.org/MartinMorterol/glp/src/dev/include/… or here github.com/edouarda/brigand/blob/master/include/brigand/…

– Martin Morterol
Apr 19 at 12:53






Well you can revert the order of the argument then unroll left to right. You may look an implementation of revert here : bitbucket.org/MartinMorterol/glp/src/dev/include/… or here github.com/edouarda/brigand/blob/master/include/brigand/…

– Martin Morterol
Apr 19 at 12:53













3 Answers
3






active

oldest

votes


















6














Here is an utility to instatiate a template with a reverse order of template parameters:



#include <type_traits>
#include <tuple>

template <template <typename...> typename Template, typename ...Arg>
struct RevertHelper;

template <template <typename > typename Template, typename Arg>
struct RevertHelper<Template, Arg>

using Result = Template<Arg>;
;

template <template <typename... > typename Template, typename Head, typename ...Tail>
struct RevertHelper<Template, Head, Tail...>

private:
template <typename ...XArgs>
using BindToTail = Template<XArgs..., Head>;

public:

using Result = typename RevertHelper<BindToTail, Tail...>::Result;
;

static_assert(std::is_same_v<typename RevertHelper<std::tuple, int, double>::Result, std::tuple<double, int>>, "");


So if you need to instantiate Foo with template pack Args... being reversed you can use



typename RevertHelper<Foo, Args...>::Result


To do the parameter pack expansion the way you want, dispatch to the reversed implementation:



namespace internal 
template <typename... T>
class FooHelper;
template <typename T>
class FooHelper<T> /* base implementation */
template <typename L, typename R, typename... Rs>
class FooHelper<T>
private:
Foo<T, Rs...> foo_helper_;
;

template <typename... T>
class Foo
typename RevertHelper<internal::FooHelper, T...>::Result foo_helper_;
;





share|improve this answer

























  • So the idea is that the actually usable class inverses the order and then dispatches to a class that reverses the order, and do the unpacking in that helper class?

    – IdeaHat
    Apr 19 at 13:22











  • "thanks i hate it" :-) . Added the code example. So much boilerplate to do something so simple.

    – IdeaHat
    Apr 19 at 13:32











  • @IdeaHat, yes I meant something like that. You can even make "Foo" a template alias to a RevertHelper<internal::FooHelper, T...>

    – Dmitry Gordon
    Apr 19 at 13:34











  • Not while providing a base case specialization

    – IdeaHat
    Apr 19 at 14:49


















4















I'm not sure why the compiler cannot map Foo<T, Rs..., R> to the initial template declaration Foo<T...> and enforces the parameter pack declaration order there.




Because partial ordering is already a really complex algorithm and adding extra complexity to that is fraught with peril. There was a proposal to make this work, which had this example:




template <class A, class... B, class C> void foo(A a, B... b, C c);
foo(1, 2, 3, 4); // b is deduced as [2, 3]



Straightforward enough right? Now, what if C has a default argument? What does this do:



template <class A, class... B, class C=int> void foo(A a, B... b, C c=5);
foo(1, 2, 3, 4);


There are two interpretations of this:




  • b is deduced as the pack 2, 3 and c is deduced as 4


  • b is deduced as the pack 2, 3, 4 and c is deduced as 5

Which is intended? Or do we just disallow default arguments after a function parameter pack?




Unfortunately, we have no nice pack indexing mechanism. In the meantime, just use Boost.Mp11:



template <typename... T>
class Foo;

template <typename T>
class Foo<T> /* base case implementation*/;

template <typename T, typename... Rs>
class Foo<T, Rs...>
private:
using R = mp_back<Foo>;
mp_pop_back<Foo> foo_;
;





share|improve this answer























  • "Or do we just disallow default arguments after a function parameter pack?" - the obvious answer to me here seems "yes". But I guess that didn't fly with EWG?

    – Vittorio Romeo
    Apr 20 at 10:37


















3














Pattern matching in C++ template patterns is intentionally simplified for sake of simplicity of algorithm and understanding.



Take a look at hypothetical algorithm if this could be possible:



  1. Get some declaration: using X = Foo<int, char, bool, double>;

  2. Compiler checks specializations: first one is Foo - it's dropped.

  3. Compiler checks specializations: second one is your Foo<T, Rs..., R>


    1. T is int, we're fine.


    2. R's can be emtpy, let's try to skip it.


    3. R is char, but we're at the end of specialization parameters, let's get back to 2.


    4. R's is char


    5. R is bool, but we're at the end of specialization parameters, let's get back to 2.


    6. R's is char, bool


    7. R is double, we're fine, select this one


But this is only one scenario: another one would be to eat all parameters to the end and cut off one by one in order to try to match it. This can be problematic, because such template specialization would be inherently ambiguous with another possible specialization that doesn't seem to be an ambiguity here:



template<typename T, typename S>
class Foo<T, S> ;





share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55762106%2fhow-to-unroll-a-parameter-pack-from-right-to-left%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    6














    Here is an utility to instatiate a template with a reverse order of template parameters:



    #include <type_traits>
    #include <tuple>

    template <template <typename...> typename Template, typename ...Arg>
    struct RevertHelper;

    template <template <typename > typename Template, typename Arg>
    struct RevertHelper<Template, Arg>

    using Result = Template<Arg>;
    ;

    template <template <typename... > typename Template, typename Head, typename ...Tail>
    struct RevertHelper<Template, Head, Tail...>

    private:
    template <typename ...XArgs>
    using BindToTail = Template<XArgs..., Head>;

    public:

    using Result = typename RevertHelper<BindToTail, Tail...>::Result;
    ;

    static_assert(std::is_same_v<typename RevertHelper<std::tuple, int, double>::Result, std::tuple<double, int>>, "");


    So if you need to instantiate Foo with template pack Args... being reversed you can use



    typename RevertHelper<Foo, Args...>::Result


    To do the parameter pack expansion the way you want, dispatch to the reversed implementation:



    namespace internal 
    template <typename... T>
    class FooHelper;
    template <typename T>
    class FooHelper<T> /* base implementation */
    template <typename L, typename R, typename... Rs>
    class FooHelper<T>
    private:
    Foo<T, Rs...> foo_helper_;
    ;

    template <typename... T>
    class Foo
    typename RevertHelper<internal::FooHelper, T...>::Result foo_helper_;
    ;





    share|improve this answer

























    • So the idea is that the actually usable class inverses the order and then dispatches to a class that reverses the order, and do the unpacking in that helper class?

      – IdeaHat
      Apr 19 at 13:22











    • "thanks i hate it" :-) . Added the code example. So much boilerplate to do something so simple.

      – IdeaHat
      Apr 19 at 13:32











    • @IdeaHat, yes I meant something like that. You can even make "Foo" a template alias to a RevertHelper<internal::FooHelper, T...>

      – Dmitry Gordon
      Apr 19 at 13:34











    • Not while providing a base case specialization

      – IdeaHat
      Apr 19 at 14:49















    6














    Here is an utility to instatiate a template with a reverse order of template parameters:



    #include <type_traits>
    #include <tuple>

    template <template <typename...> typename Template, typename ...Arg>
    struct RevertHelper;

    template <template <typename > typename Template, typename Arg>
    struct RevertHelper<Template, Arg>

    using Result = Template<Arg>;
    ;

    template <template <typename... > typename Template, typename Head, typename ...Tail>
    struct RevertHelper<Template, Head, Tail...>

    private:
    template <typename ...XArgs>
    using BindToTail = Template<XArgs..., Head>;

    public:

    using Result = typename RevertHelper<BindToTail, Tail...>::Result;
    ;

    static_assert(std::is_same_v<typename RevertHelper<std::tuple, int, double>::Result, std::tuple<double, int>>, "");


    So if you need to instantiate Foo with template pack Args... being reversed you can use



    typename RevertHelper<Foo, Args...>::Result


    To do the parameter pack expansion the way you want, dispatch to the reversed implementation:



    namespace internal 
    template <typename... T>
    class FooHelper;
    template <typename T>
    class FooHelper<T> /* base implementation */
    template <typename L, typename R, typename... Rs>
    class FooHelper<T>
    private:
    Foo<T, Rs...> foo_helper_;
    ;

    template <typename... T>
    class Foo
    typename RevertHelper<internal::FooHelper, T...>::Result foo_helper_;
    ;





    share|improve this answer

























    • So the idea is that the actually usable class inverses the order and then dispatches to a class that reverses the order, and do the unpacking in that helper class?

      – IdeaHat
      Apr 19 at 13:22











    • "thanks i hate it" :-) . Added the code example. So much boilerplate to do something so simple.

      – IdeaHat
      Apr 19 at 13:32











    • @IdeaHat, yes I meant something like that. You can even make "Foo" a template alias to a RevertHelper<internal::FooHelper, T...>

      – Dmitry Gordon
      Apr 19 at 13:34











    • Not while providing a base case specialization

      – IdeaHat
      Apr 19 at 14:49













    6












    6








    6







    Here is an utility to instatiate a template with a reverse order of template parameters:



    #include <type_traits>
    #include <tuple>

    template <template <typename...> typename Template, typename ...Arg>
    struct RevertHelper;

    template <template <typename > typename Template, typename Arg>
    struct RevertHelper<Template, Arg>

    using Result = Template<Arg>;
    ;

    template <template <typename... > typename Template, typename Head, typename ...Tail>
    struct RevertHelper<Template, Head, Tail...>

    private:
    template <typename ...XArgs>
    using BindToTail = Template<XArgs..., Head>;

    public:

    using Result = typename RevertHelper<BindToTail, Tail...>::Result;
    ;

    static_assert(std::is_same_v<typename RevertHelper<std::tuple, int, double>::Result, std::tuple<double, int>>, "");


    So if you need to instantiate Foo with template pack Args... being reversed you can use



    typename RevertHelper<Foo, Args...>::Result


    To do the parameter pack expansion the way you want, dispatch to the reversed implementation:



    namespace internal 
    template <typename... T>
    class FooHelper;
    template <typename T>
    class FooHelper<T> /* base implementation */
    template <typename L, typename R, typename... Rs>
    class FooHelper<T>
    private:
    Foo<T, Rs...> foo_helper_;
    ;

    template <typename... T>
    class Foo
    typename RevertHelper<internal::FooHelper, T...>::Result foo_helper_;
    ;





    share|improve this answer















    Here is an utility to instatiate a template with a reverse order of template parameters:



    #include <type_traits>
    #include <tuple>

    template <template <typename...> typename Template, typename ...Arg>
    struct RevertHelper;

    template <template <typename > typename Template, typename Arg>
    struct RevertHelper<Template, Arg>

    using Result = Template<Arg>;
    ;

    template <template <typename... > typename Template, typename Head, typename ...Tail>
    struct RevertHelper<Template, Head, Tail...>

    private:
    template <typename ...XArgs>
    using BindToTail = Template<XArgs..., Head>;

    public:

    using Result = typename RevertHelper<BindToTail, Tail...>::Result;
    ;

    static_assert(std::is_same_v<typename RevertHelper<std::tuple, int, double>::Result, std::tuple<double, int>>, "");


    So if you need to instantiate Foo with template pack Args... being reversed you can use



    typename RevertHelper<Foo, Args...>::Result


    To do the parameter pack expansion the way you want, dispatch to the reversed implementation:



    namespace internal 
    template <typename... T>
    class FooHelper;
    template <typename T>
    class FooHelper<T> /* base implementation */
    template <typename L, typename R, typename... Rs>
    class FooHelper<T>
    private:
    Foo<T, Rs...> foo_helper_;
    ;

    template <typename... T>
    class Foo
    typename RevertHelper<internal::FooHelper, T...>::Result foo_helper_;
    ;






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Apr 19 at 13:30









    IdeaHat

    5,7581341




    5,7581341










    answered Apr 19 at 13:05









    Dmitry GordonDmitry Gordon

    1,214614




    1,214614












    • So the idea is that the actually usable class inverses the order and then dispatches to a class that reverses the order, and do the unpacking in that helper class?

      – IdeaHat
      Apr 19 at 13:22











    • "thanks i hate it" :-) . Added the code example. So much boilerplate to do something so simple.

      – IdeaHat
      Apr 19 at 13:32











    • @IdeaHat, yes I meant something like that. You can even make "Foo" a template alias to a RevertHelper<internal::FooHelper, T...>

      – Dmitry Gordon
      Apr 19 at 13:34











    • Not while providing a base case specialization

      – IdeaHat
      Apr 19 at 14:49

















    • So the idea is that the actually usable class inverses the order and then dispatches to a class that reverses the order, and do the unpacking in that helper class?

      – IdeaHat
      Apr 19 at 13:22











    • "thanks i hate it" :-) . Added the code example. So much boilerplate to do something so simple.

      – IdeaHat
      Apr 19 at 13:32











    • @IdeaHat, yes I meant something like that. You can even make "Foo" a template alias to a RevertHelper<internal::FooHelper, T...>

      – Dmitry Gordon
      Apr 19 at 13:34











    • Not while providing a base case specialization

      – IdeaHat
      Apr 19 at 14:49
















    So the idea is that the actually usable class inverses the order and then dispatches to a class that reverses the order, and do the unpacking in that helper class?

    – IdeaHat
    Apr 19 at 13:22





    So the idea is that the actually usable class inverses the order and then dispatches to a class that reverses the order, and do the unpacking in that helper class?

    – IdeaHat
    Apr 19 at 13:22













    "thanks i hate it" :-) . Added the code example. So much boilerplate to do something so simple.

    – IdeaHat
    Apr 19 at 13:32





    "thanks i hate it" :-) . Added the code example. So much boilerplate to do something so simple.

    – IdeaHat
    Apr 19 at 13:32













    @IdeaHat, yes I meant something like that. You can even make "Foo" a template alias to a RevertHelper<internal::FooHelper, T...>

    – Dmitry Gordon
    Apr 19 at 13:34





    @IdeaHat, yes I meant something like that. You can even make "Foo" a template alias to a RevertHelper<internal::FooHelper, T...>

    – Dmitry Gordon
    Apr 19 at 13:34













    Not while providing a base case specialization

    – IdeaHat
    Apr 19 at 14:49





    Not while providing a base case specialization

    – IdeaHat
    Apr 19 at 14:49













    4















    I'm not sure why the compiler cannot map Foo<T, Rs..., R> to the initial template declaration Foo<T...> and enforces the parameter pack declaration order there.




    Because partial ordering is already a really complex algorithm and adding extra complexity to that is fraught with peril. There was a proposal to make this work, which had this example:




    template <class A, class... B, class C> void foo(A a, B... b, C c);
    foo(1, 2, 3, 4); // b is deduced as [2, 3]



    Straightforward enough right? Now, what if C has a default argument? What does this do:



    template <class A, class... B, class C=int> void foo(A a, B... b, C c=5);
    foo(1, 2, 3, 4);


    There are two interpretations of this:




    • b is deduced as the pack 2, 3 and c is deduced as 4


    • b is deduced as the pack 2, 3, 4 and c is deduced as 5

    Which is intended? Or do we just disallow default arguments after a function parameter pack?




    Unfortunately, we have no nice pack indexing mechanism. In the meantime, just use Boost.Mp11:



    template <typename... T>
    class Foo;

    template <typename T>
    class Foo<T> /* base case implementation*/;

    template <typename T, typename... Rs>
    class Foo<T, Rs...>
    private:
    using R = mp_back<Foo>;
    mp_pop_back<Foo> foo_;
    ;





    share|improve this answer























    • "Or do we just disallow default arguments after a function parameter pack?" - the obvious answer to me here seems "yes". But I guess that didn't fly with EWG?

      – Vittorio Romeo
      Apr 20 at 10:37















    4















    I'm not sure why the compiler cannot map Foo<T, Rs..., R> to the initial template declaration Foo<T...> and enforces the parameter pack declaration order there.




    Because partial ordering is already a really complex algorithm and adding extra complexity to that is fraught with peril. There was a proposal to make this work, which had this example:




    template <class A, class... B, class C> void foo(A a, B... b, C c);
    foo(1, 2, 3, 4); // b is deduced as [2, 3]



    Straightforward enough right? Now, what if C has a default argument? What does this do:



    template <class A, class... B, class C=int> void foo(A a, B... b, C c=5);
    foo(1, 2, 3, 4);


    There are two interpretations of this:




    • b is deduced as the pack 2, 3 and c is deduced as 4


    • b is deduced as the pack 2, 3, 4 and c is deduced as 5

    Which is intended? Or do we just disallow default arguments after a function parameter pack?




    Unfortunately, we have no nice pack indexing mechanism. In the meantime, just use Boost.Mp11:



    template <typename... T>
    class Foo;

    template <typename T>
    class Foo<T> /* base case implementation*/;

    template <typename T, typename... Rs>
    class Foo<T, Rs...>
    private:
    using R = mp_back<Foo>;
    mp_pop_back<Foo> foo_;
    ;





    share|improve this answer























    • "Or do we just disallow default arguments after a function parameter pack?" - the obvious answer to me here seems "yes". But I guess that didn't fly with EWG?

      – Vittorio Romeo
      Apr 20 at 10:37













    4












    4








    4








    I'm not sure why the compiler cannot map Foo<T, Rs..., R> to the initial template declaration Foo<T...> and enforces the parameter pack declaration order there.




    Because partial ordering is already a really complex algorithm and adding extra complexity to that is fraught with peril. There was a proposal to make this work, which had this example:




    template <class A, class... B, class C> void foo(A a, B... b, C c);
    foo(1, 2, 3, 4); // b is deduced as [2, 3]



    Straightforward enough right? Now, what if C has a default argument? What does this do:



    template <class A, class... B, class C=int> void foo(A a, B... b, C c=5);
    foo(1, 2, 3, 4);


    There are two interpretations of this:




    • b is deduced as the pack 2, 3 and c is deduced as 4


    • b is deduced as the pack 2, 3, 4 and c is deduced as 5

    Which is intended? Or do we just disallow default arguments after a function parameter pack?




    Unfortunately, we have no nice pack indexing mechanism. In the meantime, just use Boost.Mp11:



    template <typename... T>
    class Foo;

    template <typename T>
    class Foo<T> /* base case implementation*/;

    template <typename T, typename... Rs>
    class Foo<T, Rs...>
    private:
    using R = mp_back<Foo>;
    mp_pop_back<Foo> foo_;
    ;





    share|improve this answer














    I'm not sure why the compiler cannot map Foo<T, Rs..., R> to the initial template declaration Foo<T...> and enforces the parameter pack declaration order there.




    Because partial ordering is already a really complex algorithm and adding extra complexity to that is fraught with peril. There was a proposal to make this work, which had this example:




    template <class A, class... B, class C> void foo(A a, B... b, C c);
    foo(1, 2, 3, 4); // b is deduced as [2, 3]



    Straightforward enough right? Now, what if C has a default argument? What does this do:



    template <class A, class... B, class C=int> void foo(A a, B... b, C c=5);
    foo(1, 2, 3, 4);


    There are two interpretations of this:




    • b is deduced as the pack 2, 3 and c is deduced as 4


    • b is deduced as the pack 2, 3, 4 and c is deduced as 5

    Which is intended? Or do we just disallow default arguments after a function parameter pack?




    Unfortunately, we have no nice pack indexing mechanism. In the meantime, just use Boost.Mp11:



    template <typename... T>
    class Foo;

    template <typename T>
    class Foo<T> /* base case implementation*/;

    template <typename T, typename... Rs>
    class Foo<T, Rs...>
    private:
    using R = mp_back<Foo>;
    mp_pop_back<Foo> foo_;
    ;






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Apr 19 at 13:59









    BarryBarry

    188k21337618




    188k21337618












    • "Or do we just disallow default arguments after a function parameter pack?" - the obvious answer to me here seems "yes". But I guess that didn't fly with EWG?

      – Vittorio Romeo
      Apr 20 at 10:37

















    • "Or do we just disallow default arguments after a function parameter pack?" - the obvious answer to me here seems "yes". But I guess that didn't fly with EWG?

      – Vittorio Romeo
      Apr 20 at 10:37
















    "Or do we just disallow default arguments after a function parameter pack?" - the obvious answer to me here seems "yes". But I guess that didn't fly with EWG?

    – Vittorio Romeo
    Apr 20 at 10:37





    "Or do we just disallow default arguments after a function parameter pack?" - the obvious answer to me here seems "yes". But I guess that didn't fly with EWG?

    – Vittorio Romeo
    Apr 20 at 10:37











    3














    Pattern matching in C++ template patterns is intentionally simplified for sake of simplicity of algorithm and understanding.



    Take a look at hypothetical algorithm if this could be possible:



    1. Get some declaration: using X = Foo<int, char, bool, double>;

    2. Compiler checks specializations: first one is Foo - it's dropped.

    3. Compiler checks specializations: second one is your Foo<T, Rs..., R>


      1. T is int, we're fine.


      2. R's can be emtpy, let's try to skip it.


      3. R is char, but we're at the end of specialization parameters, let's get back to 2.


      4. R's is char


      5. R is bool, but we're at the end of specialization parameters, let's get back to 2.


      6. R's is char, bool


      7. R is double, we're fine, select this one


    But this is only one scenario: another one would be to eat all parameters to the end and cut off one by one in order to try to match it. This can be problematic, because such template specialization would be inherently ambiguous with another possible specialization that doesn't seem to be an ambiguity here:



    template<typename T, typename S>
    class Foo<T, S> ;





    share|improve this answer





























      3














      Pattern matching in C++ template patterns is intentionally simplified for sake of simplicity of algorithm and understanding.



      Take a look at hypothetical algorithm if this could be possible:



      1. Get some declaration: using X = Foo<int, char, bool, double>;

      2. Compiler checks specializations: first one is Foo - it's dropped.

      3. Compiler checks specializations: second one is your Foo<T, Rs..., R>


        1. T is int, we're fine.


        2. R's can be emtpy, let's try to skip it.


        3. R is char, but we're at the end of specialization parameters, let's get back to 2.


        4. R's is char


        5. R is bool, but we're at the end of specialization parameters, let's get back to 2.


        6. R's is char, bool


        7. R is double, we're fine, select this one


      But this is only one scenario: another one would be to eat all parameters to the end and cut off one by one in order to try to match it. This can be problematic, because such template specialization would be inherently ambiguous with another possible specialization that doesn't seem to be an ambiguity here:



      template<typename T, typename S>
      class Foo<T, S> ;





      share|improve this answer



























        3












        3








        3







        Pattern matching in C++ template patterns is intentionally simplified for sake of simplicity of algorithm and understanding.



        Take a look at hypothetical algorithm if this could be possible:



        1. Get some declaration: using X = Foo<int, char, bool, double>;

        2. Compiler checks specializations: first one is Foo - it's dropped.

        3. Compiler checks specializations: second one is your Foo<T, Rs..., R>


          1. T is int, we're fine.


          2. R's can be emtpy, let's try to skip it.


          3. R is char, but we're at the end of specialization parameters, let's get back to 2.


          4. R's is char


          5. R is bool, but we're at the end of specialization parameters, let's get back to 2.


          6. R's is char, bool


          7. R is double, we're fine, select this one


        But this is only one scenario: another one would be to eat all parameters to the end and cut off one by one in order to try to match it. This can be problematic, because such template specialization would be inherently ambiguous with another possible specialization that doesn't seem to be an ambiguity here:



        template<typename T, typename S>
        class Foo<T, S> ;





        share|improve this answer















        Pattern matching in C++ template patterns is intentionally simplified for sake of simplicity of algorithm and understanding.



        Take a look at hypothetical algorithm if this could be possible:



        1. Get some declaration: using X = Foo<int, char, bool, double>;

        2. Compiler checks specializations: first one is Foo - it's dropped.

        3. Compiler checks specializations: second one is your Foo<T, Rs..., R>


          1. T is int, we're fine.


          2. R's can be emtpy, let's try to skip it.


          3. R is char, but we're at the end of specialization parameters, let's get back to 2.


          4. R's is char


          5. R is bool, but we're at the end of specialization parameters, let's get back to 2.


          6. R's is char, bool


          7. R is double, we're fine, select this one


        But this is only one scenario: another one would be to eat all parameters to the end and cut off one by one in order to try to match it. This can be problematic, because such template specialization would be inherently ambiguous with another possible specialization that doesn't seem to be an ambiguity here:



        template<typename T, typename S>
        class Foo<T, S> ;






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Apr 19 at 13:20









        Stack Danny

        2,173932




        2,173932










        answered Apr 19 at 13:04









        Michał ŁośMichał Łoś

        518313




        518313



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55762106%2fhow-to-unroll-a-parameter-pack-from-right-to-left%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Wikipedia:Vital articles Мазмуну Biography - Өмүр баян Philosophy and psychology - Философия жана психология Religion - Дин Social sciences - Коомдук илимдер Language and literature - Тил жана адабият Science - Илим Technology - Технология Arts and recreation - Искусство жана эс алуу History and geography - Тарых жана география Навигация менюсу

            Bruxelas-Capital Índice Historia | Composición | Situación lingüística | Clima | Cidades irmandadas | Notas | Véxase tamén | Menú de navegacióneO uso das linguas en Bruxelas e a situación do neerlandés"Rexión de Bruxelas Capital"o orixinalSitio da rexiónPáxina de Bruselas no sitio da Oficina de Promoción Turística de Valonia e BruxelasMapa Interactivo da Rexión de Bruxelas-CapitaleeWorldCat332144929079854441105155190212ID28008674080552-90000 0001 0666 3698n94104302ID540940339365017018237

            What should I write in an apology letter, since I have decided not to join a company after accepting an offer letterShould I keep looking after accepting a job offer?What should I do when I've been verbally told I would get an offer letter, but still haven't gotten one after 4 weeks?Do I accept an offer from a company that I am not likely to join?New job hasn't confirmed starting date and I want to give current employer as much notice as possibleHow should I address my manager in my resignation letter?HR delayed background verification, now jobless as resignedNo email communication after accepting a formal written offer. How should I phrase the call?What should I do if after receiving a verbal offer letter I am informed that my written job offer is put on hold due to some internal issues?Should I inform the current employer that I am about to resign within 1-2 weeks since I have signed the offer letter and waiting for visa?What company will do, if I send their offer letter to another company