Sokeks
Sokeks

Reputation: 47

Compiler warning for Template case, that should be covered by Template Specialization

During my coding in C++98 I get a strange compiler warning that I do not understand:( See:

I have a file TemplateSpecialization.hpp:

namespace TemplateNamespace
{
    template <typename T> T getParam(int param)
    {
        return static_cast<T>(param);
    }
}

struct A
{
    A () : aaa(10) {}
    int aaa;
    template <typename T> T getAaa()
    {
        return TemplateNamespace::getParam<T>(aaa);
    }
};

and a file TemplateSpecialization.cpp:

#include "TemplateSpecialization.hpp"
#include <string>
#include <sstream>

namespace TemplateNamespace {
    template<> std::string getParam<std::string>(int param)
    {
        std::stringstream ss;
        ss << param;
        return ss.str();
    }
}

and when I call this function anywhere in other .CPP files, e.g. Test.cpp by

A a; std::string s = a.getAaa<std::string>();

and compile everything with gcc version 4.8.2 I get this warning:

In file included from /var/fpwork/sokeks/Test.cpp:22:0:
    /var/fpwork/sokeks/TemplateSpecialization.hpp: In instantiation of 'T TemplateNamespace::getParam(int) [with T = std::basic_string<char>]':
    /var/fpwork/sokeks/TemplateSpecialization.hpp:15:50:   required from 'T A::getAaa() [with T = std::basic_string<char>]'
    /var/fpwork/sokeks/Test.cpp:161:43:   required from here
    /var/fpwork/sokeks/TemplateSpecialization.hpp:5:36: warning: invalid conversion from 'int' to 'const char*' [-fpermissive]
             return static_cast<T>(param);
                                    ^

And I totally do not understand, what causes that warning! Why does at all compiler point out to the template function that is specialized!? And what exactly does it mean? I do use std::string, not const char*.

Thx in advance for help!

Upvotes: 1

Views: 127

Answers (1)

Marco A.
Marco A.

Reputation: 43662

It's a visibility problem: the specialization is into another compilation unit and it's not visibile when the template is required to be instantiated. Put the templates and declarations into your header file, put the definition for the fully specialized function into the cpp file and use some include guards:

TemplateSpecialization.hpp

#pragma once

#include <string>
#include <sstream>

namespace TemplateNamespace
{
    template <typename T> T getParam(int param)
    {
        return static_cast<T>(param);
    }

    template<> std::string getParam<std::string>(int param);
}

struct A
{
    A() : aaa(10) {}
    int aaa;
    template <typename T> T getAaa()
    {
        return TemplateNamespace::getParam<T>(aaa);
    }
};

TemplateSpecialization.cpp

#include "TemplateSpecialization.hpp"

template<> std::string TemplateNamespace::getParam<std::string>(int param)
{
    std::stringstream ss;
    ss << param;
    return ss.str();
}

Upvotes: 3

Related Questions