3

So I've got a templatized class and I want to overload the behavior of a function when I have specific type, say char. For all other types, let them do their own thing. However, c++ won't let me overload the function.

Why can't I overload this function? I really really do not want to do template specialization, because then I've got duplicate the entire class.

Here is a toy example demonstrating the problem: http://codepad.org/eTgLG932

The same code posted here for your reading pleasure:

#include <iostream>
#include <cstdlib>
#include <string>

struct Bar
{
  std::string blah() { return "blah"; }
};

template <typename T>
struct Foo
{
public:
  std::string doX()
  {
    return m_getY(my_t);
  }

private:
  std::string m_getY(char* p_msg)
  {
    return std::string(p_msg);
  }

  std::string m_getY(T* p_msg)
  {
    return p_msg->blah();
  }

  T my_t;
};

int main(int, char**)
{
  Foo<char> x;
  Foo<Bar> y;
  std::cout << "x " << x.doX() << std::endl;
  return EXIT_SUCCESS;
}

Thank you everyone for your suggestions. Two valid solutions have been presented. I can either specialize the doX method, or specialize m_getY() method.

At the end of the day I prefer to keep my specializations private rather than public so I'm accepting Krill's answer.

anio
  • 8,903
  • 7
  • 35
  • 53

4 Answers4

7

You can specialize just one function out of an entire template class on a specific type without specializing the entire class. It would look like this:

template <> void Foo<char>::doX() {
     /* custom implementation here */
}

You rarely see this in practice, but this is totally legal C++ code.

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • +1 This works as long as the member function is not also a template itself. – ildjarn Jun 29 '12 at 20:45
  • I also tried this. This works in MSVC. Although this is really really bad feature. @templatetypedef, is this explicitly allowed by the standard? – Kirill Kobelev Jun 29 '12 at 21:17
  • 1
    @KirillKobelev- Yes, this is allowed by the standard. I don't think it's a "really really bad feature;" it's just unusual. – templatetypedef Jun 29 '12 at 21:21
  • @templatetypedef, allowed is close to "not denied". The question was about "explicitly allowed". If would a member of C++ comettee, I would vote down this feature. With fixed types, this is just an unelegant work around the prohibition to have these 2 methods in the template class in the first place. I will try this for partial specialization. – Kirill Kobelev Jun 29 '12 at 22:41
  • Partial specialization (original class template has 2 params; method specialization fixes only one param) it does not seem to work in MSVC. @templatetypedef, do you think it should? – Kirill Kobelev Jun 29 '12 at 22:59
  • @KirillKobelev- No, this should not work. The language spec specifically allows full specializations this way, but not partial specializations. I honestly don't know why. – templatetypedef Jun 29 '12 at 23:57
  • Thanks. This is a little bit better that partial specs are not allowed. Then for me this 'specialization' is nothing but a simple method that was introduced in the original post... Thanks again for your help. – Kirill Kobelev Jun 30 '12 at 02:42
3
  std::string m_getY(char* p_msg)
  {
    return std::string(p_msg);
  }

  std::string m_getY(T* p_msg)
  {
    return p_msg->blah();
  }

The problem here is that when T is char, you end up with two functions with identical signature.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
1

You can make your method m_getY a member function template. And them make specialization of this function template for char* or simply define a method with a char* argument. In this case you will not have to duplicate the whole class.

Kirill Kobelev
  • 10,252
  • 6
  • 30
  • 51
  • The standard is very explicit that template of the function and simple function with fixed types of parameters can coexist in the overload bucket. – Kirill Kobelev Jun 29 '12 at 22:36
  • @KirillKobelev this ("simple function with fixed types of parameters") is not a specialisation of a template, contradicting your answer. – Walter Jun 30 '12 at 09:39
  • Thanks for the note. I improved my post. Unfortunately I was thinking about different things when I was writing the answer and the comment. – Kirill Kobelev Jun 30 '12 at 09:49
1
std::string m_getY(char* p_msg)
{
  return std::string(p_msg);
}

template<typename U> 
std::string m_getY(U* p_msg)
{
  return p_msg->blah();
}

will not conflict with each other (and the former is not a specialisation of the latter, as it is not a template)

Walter
  • 44,150
  • 20
  • 113
  • 196