c++c++11boostboost-variantboost-any

C++ Templates access a function with different types


So What I'm trying to do is something like this.

I have a template struct like this one:

template <typename T>
struct TemplateTest
{
    void test(T a)
    {
        switch (typeid(boost::any_cast<T>(a)))
        {
        case typeid(int):
            {
                std::cout << "INT";
                break;
            }
        case typeid(float):
            {
                std::cout << "FLOAT";
                break;
            }
        case typeid(double):
            {
                std::cout << "DOUBLE";
                break;
            }
        default:
            {
                std::cout << "OTHER";
                break;
            };
        }
    }
};

And I want to make a vector with different types of that struct and after just use a for-loop to iterate over all my elements and call this function form all of them.

What I would like to have will be something like this:

typedef boost::variant<TemplateTest<float>(), TemplateTest<double>(), TemplateTest<int>() > variant;
typedef std::vector<variant> TestVar;
TestVar d;
d.push_back(new TemplateTest<float>());
d.push_back(new TemplateTest<double>());
d.push_back(new TemplateTest<int>());
for (auto value : d)
{
    value.test(5);
}

Is out there any way to do this without using a specific cast of my type before my function call?


Solution

  • If you want a single function doing different things for a fixed number of types, you want to use overloaded functions, not templates.

    void test(int)
    {
       std::cout << "INT";
    }
    

    If you have a sane default that works for more than one type, you can use template specialization. You already have a struct template wrapping the functions, which is generally a good idea.

    template <typename T>
    struct TemplateTest
    {
        void test(T a)
        {
            std::cout << "OTHER";
        }
    };
    
    template<>
    struct TemplateTest<int>
    {
        void test(int a)
        {
            std::cout << "INT";
        }
    };
    

    If, as in this very specific case of oversimplification all that is different is the string, you can use variable templates:

    template<typename T>
    constexpr char* Typename = "DEFAULT";
    
    template<>
    constexpr char* Typename<int> = "INT";
    
    template <typename T>
    struct TemplateTest
    {
        void test(T a)
        {
            std::cout << Typename<T>;
        }
    };
    

    Live example of the last one here. You see that you probably wanted the test function to be static.