2

I am constructing a library that makes use of expression templates, where I make heavily use of templated functions in classes. All my code is running and recently I decided to make the main class templated to allow for using it on data of different kinds. However, I can no longer specialize my functions. How do I solve this? I have attached a small test program that shows the problem.

My previous Animal class was not templated and then this code works fine.

#include<iostream>
#include<vector>

// Example templated class with templated function
template<class T>
class Animals
{
  public:
    template<class X>
    void printFood(const X& x) const { std::cout << "We eat " << x << "!" << std::endl; }

  private:
    std::vector<T> animals;
};

// How do I specialize?
template<class T> template<>
void Animals<T>::printFood(const unsigned int& x) const { std::cout << "We don't want to eat " << x << "!" << std::endl; }

// Main loop;
int main()
{
  Animals<double> doubleAnimals;

  const int banana = 42;
  doubleAnimals.printFood(banana);

  const unsigned int apple = 666;
  doubleAnimals.printFood(apple);

  return 0;
}
Chiel
  • 6,006
  • 2
  • 32
  • 57
  • 1
    Don't specialize functions, overload them. Here is an excellent article by Herb Sutter: [Why Not Specialize Function Templates?](http://www.gotw.ca/publications/mill17.htm) – bolov Jan 27 '15 at 10:13
  • The problem with expression templates is that the potential list of types is infinite, how do I deal with overloading then? – Chiel Jan 27 '15 at 10:16
  • depends. How does the infinite list of types looks like? – bolov Jan 27 '15 at 10:22
  • So construct types from a tree that describes one calculation, so `a + b + c + d` would be the type `sum > >` etc. etc. – Chiel Jan 27 '15 at 10:24

3 Answers3

7

This simply isn't possible

[temp.expl.spec]

16 In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.

user657267
  • 20,568
  • 5
  • 58
  • 77
2

You should specialize your class first. Then specialize function:

template<> template<>
void Animals<double>::printFood(const unsigned int& x) const { std::cout << "We don't want to eat " << x << "!" << std::endl; }
SGrebenkin
  • 572
  • 4
  • 10
  • 2
    But I do not want to specialize my class first, because then I end up writing an infinite number of specializations. – Chiel Jan 27 '15 at 10:21
0

You can't partially specialize template members of non-specialized template class. This is consistent with prohibiting partial specialization of template functions (think of template class as the member function's first parameter). Use overloading instead:

template<class T>
class Animals
{
public:
    template<class X>
    void printFood(const X& x) const { std::cout << "We eat " << x << "!" << std::endl; }

    void printFood(const unsigned int& x) const { std::cout << "We don't want to eat " << x << "!" << std::endl; }

private:
    std::vector<T> animals;
};
Anton Savin
  • 40,838
  • 8
  • 54
  • 90
  • 2
    he wasn't partially specializing the function. The problem is that you can't specialize a function of a non-specialized templated class. – bolov Jan 27 '15 at 10:20
  • 1
    @bolov It's basically the same: you can consider `void Animal::printFood(X) const` as `void printFood(const Animal&, X)`, so you must specialize either both parameters or none. – Anton Savin Jan 27 '15 at 10:22
  • Is writing a templated and a non-templated version of the same function still considered overloading? – Chiel Jan 27 '15 at 10:23
  • I have put a new question concerning that http://stackoverflow.com/questions/28168290/is-a-templated-and-a-nontemplated-version-of-the-same-function-considered-an-ove – Chiel Jan 27 '15 at 10:33