Should the following program compile according to standard?
Asked Answered
T

2

10

After my discovery of incosistency between MSVC and GCC (probably clang too) in compilation and linking of the same code, I've become curious should this program actually compile and link and thus it's bug in MSVC (which reports a linker error) or should I write it differently. The program consist of 3 files:

C.h

template <typename T>
struct A
{
    void func() {};
};

template <>
void A<int>::func ();

A.cpp:

#include "C.h"
int main()
{
    A<int> x;
    x.func();
}

B.cpp:

#include "C.h"
template <>
void A<int>::func()
{
}

The resulting linker error from MSVC is:

A.obj : error LNK2019: unresolved external symbol "public: void __thiscall A::func(void)"

So basically it decides not to create symbol out of definition placed in B.cpp. The thing which makes me strongly suspect it as a bug is that moving unspecialized definition of func out of struct definition and even placing it above specialization declaration makes program linnking successful, but I would like to be sure.

So my question is - should this program be compiled and linked without errors by a conformant compiler/linker?

Twentyfour answered 6/9, 2015 at 10:37 Comment(9)
Looks like a bug to me. Are you using the latest (2015) version of MSVC?Brachio
@MatsPetersson Yes, 2015.Twentyfour
Your code compiles fine with clang++ as well. It is a bit weird tho', since you are essentially providing two definitions for func - I'm not enough of a language-lawyer to say if that is correct or not (I think it is)Brachio
Also compiles with clang++ -std=c++03 by the way.Brachio
How exactly do you compile and link this? It works fine with MSVC 2013.Subconscious
@ChristianHackl In simplest manner possible, see i.imgur.com/d9LxuOy.pngTwentyfour
Looking at the code in the b.obj with dumpbin (compiled with VS2015), the definition of A<int>::func is not in the file. Adding a different function to call it (so that it is used), or even just a global variable that points to it, adds the function definition to the object file.Willettawillette
@Willettawillette I knew it and I checked with dumbin too, my example is mostly constructed to show the problem without using tools like dumpbin. The real point of asking a question though is that it doesn't happen with other compilers which is a source of a little confusion for me :)Twentyfour
My comment was mainly to show what the problem was, and that it is definitely a bug in the compiler, and show a workaround if someone else runs across this. Feel free to report it to Microsoft.Willettawillette
W
1

From the standard :

© ISO/IEC N4527 14.6.4.1 Point of instantiation [temp.point] 1 For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization and the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation of the enclosing specialization. Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.

In this case I think this means at C.h where the "scope declaration" occurs. If this is the case then your code should link with a standard compliant tool chain. I could be misinterpreting this...

Waisted answered 6/9, 2015 at 12:25 Comment(0)
G
-2

Unnamed namespaces have internal linkage. Since the template specialization is within an unnamed namespace it also has internal linkage.

To solve the problem, put the template in a named namespace or specify the specialization as 'extern'.

Galarza answered 6/9, 2015 at 17:16 Comment(1)
"unnamed namespace" doesn't mean what you seem to think it means.Maidenhair

© 2022 - 2024 — McMap. All rights reserved.