为什么dllexport编译不是专门的模板成员函数?

时间:2014-06-24 11:05:50

标签: c++ templates inheritance dllexport

我有一个基类模板,它有2个参数,T是派生类,flag表示我想激活某个功能,默认为false:

template 
<
    typename T, 
    bool flag
>
class SomeBase
{
public:
    static Info& GetInfo()
    {
        static Info& instance = CreateInfo<T>(T::ClassName());
        static bool inited = false;
        if (!inited)
        {
            Test<flag>(instance);
            inited = true;
        }
        return instance;
    }

private:
    template<bool enable>
    static void Test(Info& instance)
    {
        return;
    }
    template<>
    static void Test<true>(Info& instance)
    {
        T::Add(fields);
    }
};

并使用此基础:

class /*dllexport*/ MyClass : public SomeBase<MyClass, false>
{
public:
    // ...
};

flag模板参数设置为false,所以根据我的专长,它应该编译上面的空函数,并且编译器会这样做,这很好。

但是,如果我将dllexport添加到MyClass,那么编译器会给出C2039,其中显示'Add' is not a member of MyClass,这没有意义,因为我使用的是SomeBase flag == false

为什么添加dllexport会让编译器尝试编译错误的专业化?

////////////////////////////////////////
编辑1:
////////////////////////////////////////
根据这个链接:

http://msdn.microsoft.com/en-us/library/twa2aw10%28v=vs.100%29.aspx

声明when one or more of the base classes is a specialization of a class template是否在讨论SomeBase<MyClass, false>

如果是,the compiler implicitly applies dllexport to the specializations of class templates表示编译器正在向dllexport添加SomeBase<MyClass, false>

而且,由于我已经完全专业化static void Test(Info& instance),编译器应该选择Test()的正确版本,即Test<false>()

那么为什么选择(或编译)错误的版本(Test<true>())?

谢谢!

1 个答案:

答案 0 :(得分:0)

如果没有dllexport,当您从main调用MyClass :: GetInfo时,您将收到相同的错误。 在这种情况下,编译器正在扩展并仅编译调用的部分代码。 但是使用dllexport,它会扩展并编译所有内容。

您可以使用此

进行验证
template <typename T>
class SomeBase
{
public:
    void test()
    {
        dafsaf;
    }
private:
};

class /*__declspec(dllexport)*/ MyClass : public SomeBase<MyClass>
{
public:
    // ...
};

int main()
{
    MyClass o;
    //o.test();
    return 1;
}