Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explicit specialization after instantiation

I have the following code:

typedef vector<int> Vec;
typedef vector<Vec> VecOfVec;

template<typename Vec>
Vec DoSomething(const Vec &v);

template<>
VecOfVec DoSomething<VecOfVec>(const VecOfVec &v)
{
    VecOfVec r;
    for(auto i = v.begin(); i != v.end(); i++)
        r.push_back(DoSomething(*i));
    return r;
}

template<>
Vec DoSomething<Vec>(const Vec &v) // Error here
{
    return v; // for the sake of the example
}

I get the following error:

explicit specialization of 'DoSomething<vector<int> >' after instantiation

at the marked line.
The compiler insists that it already instantiated DoSomething<vector<int> >, while it cannot, and a simple program can prove it:

typedef vector<int> Vec;
typedef vector<Vec> VecOfVec;

template<typename Vec>
Vec DoSomething(const Vec &v);

template<>
VecOfVec DoSomething<VecOfVec>(const VecOfVec &v)
{
    VecOfVec r;
    for(auto i = v.begin(); i != v.end(); i++)
        r.push_back(DoSomething(*i));
    return r;
}

Results in unresolved external.
Why is the compiler saying it already instantiated it when it cannot and even does not? and why doesn't the compiler treat it as unresolved symbol, while the linker does? I know switching the method order solves it, but I want to know why is the compiler doing it.

like image 645
Dani Avatar asked Oct 14 '11 22:10

Dani


1 Answers

The code requested an implicit instantiation at DoSomething(*i). The fact that you didn't define the template in that translation unit means that it could not instantiate a specialization, hence DoSomething(*i) yields an "unresolved symbol" (linker-) error in your case. To get rid of that error, you either have to define the template in that TU, or provide an explicit instantiation directive of that template in a TU where you define the template.

The mere fact that the code requested an implicit instantiation for specialization DoSomething<vector<int> > before you explicitly provided that specialization is enough for the program to become ill-formed (without a diagnostic being required though; the compiler does a good job here which it is not required to do).

As @CharlesBailey helpfully notes, declaring the explicit specialization is perfectly sufficient; a definition of it can be given elsewhere, even outside of the using TU.

like image 135
Johannes Schaub - litb Avatar answered Nov 25 '22 13:11

Johannes Schaub - litb