I've been tracking an error in a huge project for 3 days and finally get a minimum reproducable example. I want to share this problem and ask some questions on the weird behavior of Visual Studio.
When you export a class that inherits from a instantiated template class , like
class __declspec(dllexport) classA : public Template<double>{}
MSVC will also export the instantiated template class Template<double> in DLL.
If the consumer include "template.h" in his code then instantiate a Template<double>, qnd at the same time, link to the above DLL, he will get two definition of Template<double>, which causes LNK2005 and LNK1169 error. This problem is discussed in Microsoft DLL export and C++ templates.
Here is a minimum reproducable example of this problem (Full code is here):
// ----------- Project AA ------------
// aa/CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(AA)
add_library(AA SHARED classA.cpp)                          //(1)
set_target_properties(AA PROPERTIES COMPILE_FLAGS "-DBUILD_AA")
// aa/config.h
#pragma once
#ifdef _WIN32
#  ifdef BUILD_AA
#    define AA_API __declspec( dllexport )
#  else
#    define AA_API __declspec( dllimport )
#  endif
#else
#   define AA_API
#endif
// aa/template.h
#pragma once
template<class T>
class Template {
public:
    Template() {}
};
//  aa/classA.h
#pragma once
#include "config.h"
#include "template.h"
class AA_API classA : public Template<double> {         //(2)
public:
    int fun();
};
// aa/classA.cpp
#include "classA.h"
int classA::funA(){return 123;}
// ----------- Project Main ----------
//CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project(Main)
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_subdirectory(aa)
add_executable(Main main.cpp test.cpp)
target_link_libraries(Main PUBLIC AA)
// main.cpp
#include "aa/classA.h"
#include <iostream>
int main(){
    Template<double> a;                                //(3)
    //classA aa;                                       //(4)
    //std::cout << aa.funA() << std::endl;             //(5)
    return 0;
}
// test.cpp
#include "aa/template.h"
class classB {
    Template<double> t;
};
class classC : public Template<double> {};
void fun() {
    Template<double> b;                               //(6)
    //class classB;                                   //(7)
    //class classC;                                   //(8)
}
I compile the code in VS2015 Debug mode, it gives multiply defined error
1>------ Build started: Project: AA, Configuration: Debug x64 ------
1>  classA.cpp
1>  AA.vcxproj -> D:\sandbox\build\aa\Debug\AA.dll
2>------ Build started: Project: Main, Configuration: Debug x64 ------
2>  main.cpp
2>AA.lib(AA.dll) : error LNK2005: "public: __cdecl Template<double>::Template<double>(void)" (??0?$Template@N@@QEAA@XZ) already defined in test.obj
2>D:\sandbox\build\Debug\Main.exe : fatal error LNK1169: one or more multiply defined symbols found
========== Build: 1 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========
If I do ONE OF the following changes, there will be no error:
- Change to Release mode
 - Remove 
AA_APIat(2)and change link mode to STATIC at(1) - Comment 
(3)and uncomment(4)and(5) - Comment 
(6)and uncomment(7)and(8) - Compile in Linux by gcc
 - Change project parameter in VS : add 
/FORCE:MULTIPLEto Linker for project Main 
Question:
Why changes 1,2,3,4 and 5 work ? I think it's so weird that 3 and 4 can work.
How to solve this problem properly in Visual Studio ?