3

In trying to write a simple example for currying of metafunction classes, I wrote the following:

#include <type_traits>

struct first {
    template <typename T, typename U>
    using apply = T;
};

template <typename C, typename... Args>
struct curry {
    struct type {
        template <typename... OtherArgs>
        using apply = typename C::template apply<Args..., OtherArgs...>;
    };
};

int main() {
    static_assert(std::is_same<first::apply<int, char>, int>::value, ""); // OK

    using AlwaysInt = curry<first, int>::type;
    static_assert(std::is_same<AlwaysInt::apply<char>, int>::value, ""); // error
}

The second static_assert fails to compile on both gcc 5.1:

main.cpp:17:72: error: pack expansion argument for non-pack parameter 'U' of alias template 'template<class T, class U> using apply = T'
         using apply = typename C::template apply<Args..., OtherArgs...>;
                                                                        ^

and clang 3.6:

main.cpp:17:59: error: pack expansion used as argument for non-pack parameter of alias template
        using apply = typename C::template apply<Args..., OtherArgs...>;
                                                          ^~~~~~~~~~~~

Same error in both cases. However, if I outsource the application in curry to a separate metafunction:

template <typename C, typename... Args>
struct eval {
    using type = typename C::template apply<Args...>;
};

template <typename C, typename... Args>
struct curry {
    struct type {
        template <typename... OtherArgs>
        using apply = typename eval<C, Args..., OtherArgs...>::type;
    };
};

Both compilers compile just fine. Is there something wrong with the original example or is this just a bug in both compilers?

Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1430? – T.C. Aug 01 '15 at 23:36
  • @T.C. "The consensus of CWG was that this usage should be prohibited..." What? Why? – Barry Aug 01 '15 at 23:54
  • For what it's worth, VS2015 RC doesn't like it either. – R2-Dequeue Aug 02 '15 at 00:38
  • @Barry Apparently it makes the alias template non-transparent. See also assorted reports on the [GCC bugzilla](https://gcc.gnu.org/bugzilla/buglist.cgi?quicksearch=DR%201430) – T.C. Aug 02 '15 at 00:44
  • Quick fix is to make the second template parameter of first:: apply a parameter pack, but I see that this is not what your question is about. http://ideone.com/5LOp59 – Daniel Jour Aug 02 '15 at 07:21
  • @T.C. Yeah Louis Dionne's use-case in [59498](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59498) is the same as what I'm doing here. The fact that the alias is non-transparent seems less important than the fact that it doesn't work... – Barry Aug 02 '15 at 10:35
  • @T.C. Like from a language perspective, it's very odd that what I am trying to do failed by [this](http://coliru.stacked-crooked.com/a/b932e626233f3982) works fine. – Barry Aug 02 '15 at 10:39

0 Answers0