How to unroll a parameter pack from right to left





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







12















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




















12















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
















12












12








12


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,7731342




5,7731342








  • 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,7731342




    5,7731342










    answered Apr 19 at 13:05









    Dmitry GordonDmitry Gordon

    1,584616




    1,584616













    • 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

    189k21339622




    189k21339622













    • "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

            Færeyskur hestur Heimild | Tengill | Tilvísanir | LeiðsagnarvalRossið - síða um færeyska hrossið á færeyskuGott ár hjá færeyska hestinum

            He _____ here since 1970 . Answer needed [closed]What does “since he was so high” mean?Meaning of “catch birds for”?How do I ensure “since” takes the meaning I want?“Who cares here” meaningWhat does “right round toward” mean?the time tense (had now been detected)What does the phrase “ring around the roses” mean here?Correct usage of “visited upon”Meaning of “foiled rail sabotage bid”It was the third time I had gone to Rome or It is the third time I had been to Rome

            Slayer Innehåll Historia | Stil, komposition och lyrik | Bandets betydelse och framgångar | Sidoprojekt och samarbeten | Kontroverser | Medlemmar | Utmärkelser och nomineringar | Turnéer och festivaler | Diskografi | Referenser | Externa länkar | Navigeringsmenywww.slayer.net”Metal Massacre vol. 1””Metal Massacre vol. 3””Metal Massacre Volume III””Show No Mercy””Haunting the Chapel””Live Undead””Hell Awaits””Reign in Blood””Reign in Blood””Gold & Platinum – Reign in Blood””Golden Gods Awards Winners”originalet”Kerrang! Hall Of Fame””Slayer Looks Back On 37-Year Career In New Video Series: Part Two””South of Heaven””Gold & Platinum – South of Heaven””Seasons in the Abyss””Gold & Platinum - Seasons in the Abyss””Divine Intervention””Divine Intervention - Release group by Slayer””Gold & Platinum - Divine Intervention””Live Intrusion””Undisputed Attitude””Abolish Government/Superficial Love””Release “Slatanic Slaughter: A Tribute to Slayer” by Various Artists””Diabolus in Musica””Soundtrack to the Apocalypse””God Hates Us All””Systematic - Relationships””War at the Warfield””Gold & Platinum - War at the Warfield””Soundtrack to the Apocalypse””Gold & Platinum - Still Reigning””Metallica, Slayer, Iron Mauden Among Winners At Metal Hammer Awards””Eternal Pyre””Eternal Pyre - Slayer release group””Eternal Pyre””Metal Storm Awards 2006””Kerrang! Hall Of Fame””Slayer Wins 'Best Metal' Grammy Award””Slayer Guitarist Jeff Hanneman Dies””Bullet-For My Valentine booed at Metal Hammer Golden Gods Awards””Unholy Aliance””The End Of Slayer?””Slayer: We Could Thrash Out Two More Albums If We're Fast Enough...””'The Unholy Alliance: Chapter III' UK Dates Added”originalet”Megadeth And Slayer To Co-Headline 'Canadian Carnage' Trek”originalet”World Painted Blood””Release “World Painted Blood” by Slayer””Metallica Heading To Cinemas””Slayer, Megadeth To Join Forces For 'European Carnage' Tour - Dec. 18, 2010”originalet”Slayer's Hanneman Contracts Acute Infection; Band To Bring In Guest Guitarist””Cannibal Corpse's Pat O'Brien Will Step In As Slayer's Guest Guitarist”originalet”Slayer’s Jeff Hanneman Dead at 49””Dave Lombardo Says He Made Only $67,000 In 2011 While Touring With Slayer””Slayer: We Do Not Agree With Dave Lombardo's Substance Or Timeline Of Events””Slayer Welcomes Drummer Paul Bostaph Back To The Fold””Slayer Hope to Unveil Never-Before-Heard Jeff Hanneman Material on Next Album””Slayer Debut New Song 'Implode' During Surprise Golden Gods Appearance””Release group Repentless by Slayer””Repentless - Slayer - Credits””Slayer””Metal Storm Awards 2015””Slayer - to release comic book "Repentless #1"””Slayer To Release 'Repentless' 6.66" Vinyl Box Set””BREAKING NEWS: Slayer Announce Farewell Tour””Slayer Recruit Lamb of God, Anthrax, Behemoth + Testament for Final Tour””Slayer lägger ner efter 37 år””Slayer Announces Second North American Leg Of 'Final' Tour””Final World Tour””Slayer Announces Final European Tour With Lamb of God, Anthrax And Obituary””Slayer To Tour Europe With Lamb of God, Anthrax And Obituary””Slayer To Play 'Last French Show Ever' At Next Year's Hellfst””Slayer's Final World Tour Will Extend Into 2019””Death Angel's Rob Cavestany On Slayer's 'Farewell' Tour: 'Some Of Us Could See This Coming'””Testament Has No Plans To Retire Anytime Soon, Says Chuck Billy””Anthrax's Scott Ian On Slayer's 'Farewell' Tour Plans: 'I Was Surprised And I Wasn't Surprised'””Slayer””Slayer's Morbid Schlock””Review/Rock; For Slayer, the Mania Is the Message””Slayer - Biography””Slayer - Reign In Blood”originalet”Dave Lombardo””An exclusive oral history of Slayer”originalet”Exclusive! Interview With Slayer Guitarist Jeff Hanneman”originalet”Thinking Out Loud: Slayer's Kerry King on hair metal, Satan and being polite””Slayer Lyrics””Slayer - Biography””Most influential artists for extreme metal music””Slayer - Reign in Blood””Slayer guitarist Jeff Hanneman dies aged 49””Slatanic Slaughter: A Tribute to Slayer””Gateway to Hell: A Tribute to Slayer””Covered In Blood””Slayer: The Origins of Thrash in San Francisco, CA.””Why They Rule - #6 Slayer”originalet”Guitar World's 100 Greatest Heavy Metal Guitarists Of All Time”originalet”The fans have spoken: Slayer comes out on top in readers' polls”originalet”Tribute to Jeff Hanneman (1964-2013)””Lamb Of God Frontman: We Sound Like A Slayer Rip-Off””BEHEMOTH Frontman Pays Tribute To SLAYER's JEFF HANNEMAN””Slayer, Hatebreed Doing Double Duty On This Year's Ozzfest””System of a Down””Lacuna Coil’s Andrea Ferro Talks Influences, Skateboarding, Band Origins + More””Slayer - Reign in Blood””Into The Lungs of Hell””Slayer rules - en utställning om fans””Slayer and Their Fans Slashed Through a No-Holds-Barred Night at Gas Monkey””Home””Slayer””Gold & Platinum - The Big 4 Live from Sofia, Bulgaria””Exclusive! Interview With Slayer Guitarist Kerry King””2008-02-23: Wiltern, Los Angeles, CA, USA””Slayer's Kerry King To Perform With Megadeth Tonight! - Oct. 21, 2010”originalet”Dave Lombardo - Biography”Slayer Case DismissedArkiveradUltimate Classic Rock: Slayer guitarist Jeff Hanneman dead at 49.”Slayer: "We could never do any thing like Some Kind Of Monster..."””Cannibal Corpse'S Pat O'Brien Will Step In As Slayer'S Guest Guitarist | The Official Slayer Site”originalet”Slayer Wins 'Best Metal' Grammy Award””Slayer Guitarist Jeff Hanneman Dies””Kerrang! Awards 2006 Blog: Kerrang! Hall Of Fame””Kerrang! Awards 2013: Kerrang! Legend”originalet”Metallica, Slayer, Iron Maien Among Winners At Metal Hammer Awards””Metal Hammer Golden Gods Awards””Bullet For My Valentine Booed At Metal Hammer Golden Gods Awards””Metal Storm Awards 2006””Metal Storm Awards 2015””Slayer's Concert History””Slayer - Relationships””Slayer - Releases”Slayers officiella webbplatsSlayer på MusicBrainzOfficiell webbplatsSlayerSlayerr1373445760000 0001 1540 47353068615-5086262726cb13906545x(data)6033143kn20030215029