19

Is it possible to call a function defined in a non-specialised template class from a specialised template class? Here is an example of what i am attempting:

template <typename T>
struct Convert
{
 static inline void toString(unsigned num, unsigned places, std::string& str) { ... }
};

template <>
struct Convert<int8_t>
{
 static inline void toString(unsigned num, std::string& str)
 {
   Convert<int8_t>::toString(num, digitis(num), str);
 }
};

GCC complains that it can't see the non-specialised class function; i.e. I guess it only looks within the specialised class.

Any thoughts?

EDIT

Here is a more concrete example from my code (with a possible solution):

struct NonSpecial { };

template <typename T>
class Convert
{

        template <typename R>
        static inline R fromString(const register char *str, const unsigned str_len)
        {   
            R result = 0;
            //convert str to R
            return result;
        }

        friend class Convert<int8_t>;
        friend class Convert<uint8_t>;
}

template <>
struct Convert<int8_t>     
{
    static inline int8_t fromString(const register char* str, const unsigned str_len = 4)
    {
        Convert<NonSpecial>::fromString<int8_t>(str, str_len);    
    }
};

template <>
struct Convert<uint8_t>     
{
    static inline uint8_t fromString(const register char* str, const unsigned str_len = 3)
    {
        Convert<NonSpecial>::fromString<uint8_t>(str, str_len);    
    }
};

I have other functions - toString(), countDigits(), etc. I have chosen this approach so I can keep the same function names for each type (i.e. don't need toStringU32(), toString32, etc.). I considered template specialization but I don't believe this is possible.

Graeme
  • 4,514
  • 5
  • 43
  • 71
  • 1
    Why are you trying to call the non-specialized version from the specialized version of the function? In other words, if all you are doing is calling the non-specialized version, why do you need it to be specialized? – Zac Howland Jan 06 '11 at 17:13
  • the type `T` has no bearing on the static method - why is it in there in the first place? This looks like a case of template abuse, why don't you simply have overloaded free functions? – Nim Jan 06 '11 at 17:25
  • Updated post with more concrete example. – Graeme Jan 06 '11 at 18:07
  • @Zac: there are good reasons to do that. For example, different types often require the same basic processing and just need a type-specific pre- and post-processing. Calling the non-specialized version is a bit like calling the base class method in a virtual method (also often legitimate). – Konrad Rudolph Jan 09 '11 at 21:33
  • @Konrad: I get that, but in his example, all he is doing is calling the non-specialized version. – Zac Howland Jan 10 '11 at 13:15

1 Answers1

16

In general, this isn’t possible.

There are different possible solutions but they “cheat”. The first is to hoist off the actual default logic into a different function that is not specialized. Now you can call this function from both toString implementations.

The second alternative entails inheriting from the non-specialized class and passing a special tag as the template argument:

struct BaseClassTag { };

template <>
struct Convert<int8_t> : public Convert<BaseClassTag>
{
 typedef Convert<BaseClassTag> TBase;
 static inline void toString(unsigned num, std::string& str)
 {
   TBase::toString(num, digitis(num), str);
 }
};
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214