How to implement a function template entirely in terms of class template?

I am trying to understand how to implement function template in terms of class template but not sure if I am doing it the right way.
I tried finding an answer to this but could get items either exclusively related to function templates or class templates.

Does the below mention code achieves "Implement a function template entirely in terms of class template"?

1
2
3
4
5
6
7
template <typename T>
class Max {
  public:
    T max(const T& t1, const T& t2) {
      return (t1 > t2) ? t1 : t2;
    }
};


where the templated function would have been :
1
2
3
4
template <typename T>
T max(const T& t1, const T& t2) {
  return (t1 > t2) ? t1 : t2;
}


If this is not the right way, please let me know what is.

P.S. : I wanted to check this as I was reading "C++ coding standards" book and found that we should implement function template entirely in terms of class template.

Book Link for this section :

https://books.google.co.in/books?id=3xQpcCtk2okC&pg=PA142&lpg=PA142&dq=implement+function+template+entirely+in+terms+of+class+template&source=bl&ots=wsxRVOj-6D&sig=ACfU3U25Frjuoi3Ku6-Wzjw-3SHXvGEQTg&hl=en&sa=X&ved=2ahUKEwiwjYKZt6rgAhVPX30KHfzMDcUQ6AEwD3oECAIQAQ#v=onepage&q=implement%20function%20template%20entirely%20in%20terms%20of%20class%20template&f=false
Last edited on
Well, I don't have the book.

I think what was intended was very similar to what you have written, except max should have been named operator(). (This is how the standard library did things, before C++14.)

This approach is a little out-dated. Generally, we should prefer to put the function template in a class (not a class template). This lets us lift an entire overload set into a function object and pass it around. For example:
1
2
3
4
5
6
7
struct Max {
  public:
    template <typename T>
    T operator()(const T& t1, const T& t2) {
      return (t1 > t2) ? t1 : t2;
    }
};


C++14's transparent operator functors take this new approach (std::less<void>, for example). The feature proposal discusses why this is advantageous:
https://wg21.link/n3421

This thread explains the idea in a little more detail:
http://www.cplusplus.com/forum/general/244823/
Last edited on
> How to implement a function template entirely in terms of class template?

A toy example:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

// class template
template < typename A, typename B > struct foo_helper
{
    static void foo( const A&, const B& )
    { std::cout << "foo: base case\n" ; }
};

// implement the function template entirely in terms of the class template.
template < typename A, typename B > auto foo( const A& a, const B& b )
{ return foo_helper<A,B>::foo(a,b) ; }


This allows a user (or us, sometime later) to specialise the class template. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// programmers using your template will be able to partially specialize and
// explicitly specialize the class template to their heart's content without affecting the
// expected operation of the function template. This nicely avoids both the limitation that
// function templates can't be partially specialized, as well as the sometimes surprising
// effect that function template specializations don't overload. Problem solved.

struct my_type { /* ... */ };

template < typename A > struct foo_helper<A,my_type>
{
    static void foo( const A&, const my_type& )
    { std::cout << "foo: special case - second type is my_type\n" ; }
};

template < typename B > struct foo_helper<my_type,B>
{
    static void foo( const my_type&, const B& )
    { std::cout << "foo: special case - first type is my_type\n" ; }
};

template <> struct foo_helper<my_type,my_type>
{
    static void foo( const my_type&, const my_type& )
    { std::cout << "foo: special case - both types are my_type\n" ; }
};


Snippet: http://coliru.stacked-crooked.com/a/3fce0d17e90224ab
@kapil, that link takes me to the book's cover page, not to the relevant passage.
@mbozzi, apologies for a late response :/

Here is the text I referred to -


It's okay to overload function templates. Overload resolution considers all primary
templates equally, and that's why it works as you would naturally expect from your
experience with normal C++ function overloading: Whatever templates are visible are
considered for overload resolution, and the compiler simply picks the best match.
Unfortunately, it's a lot less intuitive to specialize function templates. There are two
basic reasons:
• You can't specialize function templates partially, only totally: Code that looks like
partial specialization is really just overloading instead.
• Function template specializations never participate in overloading: Therefore, any
specializations you write will not affect which template gets used, and this runs
counter to what most people would intuitively expect. After all, if you had writ
ten a nontemplate function with the identical signature instead of a function
template specialization, the nontemplate function would always be selected be
cause it's always considered to be a better match than a template.
If you're writing a function template, prefer to write it as a single function template
that should never be specialized or overloaded, and implement the function template
entirely in terms of a class template.
Topic archived. No new replies allowed.