Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explicit specialization has already been instantiated

Tags:

c++

I would like to put the implementation of the specializations of a templated function to a separate source file, but if I try to call it (in MyAction), I get this error:

Explicit specialization has already been instantiated

I have no idea, why I get this error. Example code:

main.cpp

#include <iostream>
#include <string>

#include "MyClass.h"

int main()
{
    std::cout << "Hello, " << XX::MyClass().MyMethod<1>() << std::endl;
    std::cin.get();
}

MyClass.h

#pragma once

#include <string>

namespace XX {

    struct MyClass {

        std::string MyAction() {
            return MyMethod<0>() + MyMethod<1>();
        }

        template<int>
        std::string MyMethod();

    };

    template<>
    std::string MyClass::MyMethod<0>();

    template<>
    std::string MyClass::MyMethod<1>();

}

MyClass.cpp

#include "MyClass.h"

namespace XX {

    template<>
    std::string MyClass::MyMethod<0>() {
        return "FOO";
    }

    template<>
    std::string MyClass::MyMethod<1>() {
        return "BAR";
    }

}

Is there a template instantiation rule, which I am not aware of?

like image 341
Iter Ator Avatar asked Jul 26 '19 12:07

Iter Ator


1 Answers

Ok looks like problem is an order.

When you are defining MyAction compiler tries instantiate template, but he doesn't know about specialization.

When you declare MyAction and define it in cpp after template specialization it will work.

// header part
#include <string>

namespace XX {
    struct MyClass {
        template<int>
        std::string MyMethod();
        std::string MyAction();
    };
}

// cpp part
namespace XX {
    template<>
    std::string MyClass::MyMethod<0>() {
        return "a";
    }

    template<>
    std::string MyClass::MyMethod<1>() {
        return "b";
    }

    std::string MyClass::MyAction() {
        return MyMethod<0>() + MyMethod<1>();
    }
}

See here: https://godbolt.org/z/aGSB21

Note if you move MyClass::MyAction() above MyClass::MyMethod<1>() error will come back.

Here is version where specialization is can be declared in header file: https://godbolt.org/z/kHjlne

like image 148
Marek R Avatar answered Nov 07 '22 16:11

Marek R