0

I've created Dynamic library project Foo and it has following code in the Foo.h:

#pragma once
#include <memory>
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif

class MYLIB_API Foo
{
};

template class MYLIB_API std::tr1::shared_ptr<Foo>;
typedef std::tr1::shared_ptr<Foo> FooPtr;

I use Foo class from my ConsoleApplication1:

#include "stdafx.h"
#include "Foo.h"

template class std::tr1::shared_ptr<Foo>; // (1)

int _tmain(int /*argc*/, _TCHAR* /*argv*/[])
{
    std::tr1::shared_ptr<Foo>(new Foo()); // (2)
    return 0;
}

The code above is compiled without error/warnings. I use Visual Studio 2008 (v90) toolset to compile this. Both projects is compiled with /W4.

Questions:
1. Why (1) doesn't produce any compiler errors/warnings? I've expected here something like C2011 type redefinition. I suspect (1) is ignored.
2. How many instantiations of std::tr1::shared_ptr<Foo> there are? As it is compiled, I've expected that there two instantiation: one in the Foo and another in the consoleapplication1.
3. Which instantiation (if there are many) is used at (2)?


UPDATE1:
I compiled this with Assembly With Source Code (/FAs), and seems that both Foo and ConsoleApplication1 contain implementation of shared_ptr<Foo>. Doesn't this mean that there are two shared_ptr<Foo> explicit instantiation?

Evgeny Timoshenko
  • 3,119
  • 5
  • 33
  • 53
  • 2
    [definition vs declaration?](http://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration) – Koushik Shetty Dec 03 '13 at 10:37
  • I'd be glad if someone clarify `update1`. – Evgeny Timoshenko Dec 03 '13 at 12:27
  • `update1` was kind of misconception – Evgeny Timoshenko Dec 03 '13 at 13:33
  • 1
    *"1. Why (1) doesn't produce any compiler errors/warnings?"* Well the compiler is at least not required to: [temp.spec]/5 "For a given template and a given set of *template-arguments*, an explicit instantiation definition shall appear at most once in a program [...] An implementation is not required to diagnose a violation of this rule." – dyp Dec 03 '13 at 20:56

1 Answers1

2

(1) isn't a redefinition, it's a forward declaration.

(2) There only needs to be one. I don't know why you expect any more. I supposed it's possible that a given compiler might produce more than one, but why? and it would figure pretty high on their bug list if it did.

(3) See (2).

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I've thought that line `template class std::tr1::shared_ptr;` does instantiation of `shared_ptr` with `Foo`. That's why I expected more than one – Evgeny Timoshenko Dec 03 '13 at 10:53
  • 1
    `template class std::tr1::shared_ptr;` is *not* a forward-declaration, but an explicit instantiation definition. A forward-declaration would look like this: `namespace std{namespace tr1{template class shared_ptr;}}` – dyp Dec 03 '13 at 20:51