3

I was not using the latest C++ standard for a while, today I want to implement a Haskell style List in C++ and come up with something like the following:

template<typename T>
class List {
private:
    std::function<std::tuple<T,List<T>>()> f;
    List() {}
    List(T h, List<T> t) :f([h, t]() { return std::make_tuple(h, t); }) {}
public:
    typedef T item_type;

    static List<T> empty();

    static List<T> cons(T h, List<T> t);

    template<typename N, typename C>
    static auto on(N n, C c) -> decltype(N());
};

template<typename T>
List<T> List<T>::empty() {
    return List();
}
template<typename T>
List<T> List<T>::cons(T h, List<T> t) {
    return List([h, t](std::function<void(T, List<T>)> c) {f(c); });
}

template<typename T>
template<typename N, typename C>
auto List<T>::on(N n, C c) -> decltype(N()) {
    if (f == nullptr) return n();
    else {
        T h;
        List<T> t;
        std::tie(h, t) = f();
        return c(h, t);
    }
}

template<typename T, typename R, typename F>
R foldr(List<T> l, F f, R b) {
    return l.on([b]() { return b; }, [f, b](T h, List<T> t) { return foldr(t, f, f(t, b)); });
}

The code compiles (VC 2015, not tested yet), but makes me a while to figure out the correct grammar for the function on. This is the first time I saw something like this in C++, and the double template keyword looks strange enough to me.

Question

Is this the normal way when we declare static generic methods that uses template variable not available through the class template? Can anyone point me out some clauses in the standard?

Edgar Rokjān
  • 17,245
  • 4
  • 40
  • 67
Earth Engine
  • 10,048
  • 5
  • 48
  • 78
  • 2
    That's the normal way to define *any* member function of a template class, where the member function is itself a template. For such a small function it could have been defined inline in the class, and it would have looked more "normal". – Some programmer dude Jan 17 '17 at 11:31
  • 1
    See this [How to define template function within template class in *.inl file](http://stackoverflow.com/questions/7659322/how-to-define-template-function-within-template-class-in-inl-file) – Rakete1111 Jan 17 '17 at 11:33

1 Answers1

3

Is this the normal way when we declare static generic methods that uses template variable not available through the class template?

Yes, it is normal.

Can anyone point me out some clauses in the standard?

From the n4296, 14.5.2 Member templates:

A template can be declared within a class or class template; such a template is called a member template. A member template can be defined within or outside its class definition or class template definition. A member template of a class template that is defined outside of its class template definition shall be specified with the template-parameters of the class template followed by the template-parameters of the member template. [ Example:

template<class T> struct string {
    template<class T2> int compare(const T2&);
    template<class T2> string(const string<T2>& s) { / ... / }
};

template<class T> template<class T2> int string<T>::compare(const T2& s) {
}

—end example ]

Edgar Rokjān
  • 17,245
  • 4
  • 40
  • 67