简体   繁体   中英

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.

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.

Generally it just means you didn't provide a "prototype" for the template specialization. In other words you didn't give the compiler a heads up that "hey, there is going to be a specialization for this specific type of the function, so don't plug in the wrong one."

In my case I had a template specialization in a .cpp file, and got this error. Providing a "function prototype" (which is just the template specialization header followed by a semicolon, just like a regular function prototype) fixed the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM