对基本模板类'方法的未定义引用

时间:2014-10-18 16:16:02

标签: c++ templates undefined-reference

我有很多混合的东西,它们都会导致未定义的引用。请原谅我删除代码,但是,由于我不知道哪些是个别问题,我无法搜索它们。

c.hpp

// A public class
class C {
private:
    // This class is private because it is used just for convenience;
    // it is not part of C's interface. Its methods are not defined because
    // the types for which it will be instantiated are known.
    template<typename T> 
    class Base {
    private:
        T* variable;
    public:
        // Note that this method should be available to C users, i.e., it
        // is part of the interface. Should Base then be in the public
        // section of C?
       T* get() const noexcept;
    };

public:
    // Users of this class do not care how Derived1 and Derived2 are
    // implemented. Since they were very similar in nature (think of
    // them as the various iterator versions), I decided that it would
    // be better to let the shared code be in a common template which
    // was then instantiated for a set of known parameters.
    class Derived1 : public Base<char> {
    public:
        int function() noexcept;
    };

    class Derived2 : public Base<int> {
        /* ... */
    };
};

// Should the following be included? Would it avoid unneeded implicit instantiations,
// or are those already avoided because C::Base's methods are declared but not defined?
extern template C::Base<char>;
extern template C::Base<int>;

c.cpp

template<typename T> 
T* C::Base<T>::get() const noexcept {
    return this->variable;
}

// This approach serves to hide the implementation and to shorten build times,
// while maintaining the flexibility of templates. Or so I believe.
template class C::Base<char>;
template class C::Base<int>;

// This should be another question, but... is this the correct place for
// class method attributes? There isn't much information about attributes.
[[gnu::visibility("default")]]
int C::Derived1::function() noexcept {
    return 7;
}

当代码在default可见性下编译时,它全部编译,链接并运行正常。但是,如果可见性切换到hidden,这是我想要实现的,则存在链接错误:

  

C::Base<char>::get() const

的未定义引用      

C::Base<int>::get() const

的未定义引用

其余代码链接正常,因为所有函数都标有适当的可见性属性,如图所示。由于C::Base的公共功能旨在成为公开界面的一部分,因此它们也应标有default可见性,但我不知道如何。例如,以下所有内容似乎都被禁止:

// This is not possible because templates are not "real" entities
[[gnu::visibility("default")]]
template<typename T>
T* C::Base<T>::get() const noexcept {
    return this->variable;
}


// But it isn't possible to specify it here either!
[[ /*error*/ ]] template [[ /*error*/ ]] class [[ /*error*/ ]]
    C::Base<int> [[ /*error*/ ]];

我还尝试在方法声明中指定属性:

class C {
private:
    template<typename T> 
    class Base {
    private:
        /* ... */

    public:
        [[gnu::visibility("default")]]
        T* get() const noexcept;
    };

    /* ... */
};

但它没有改变任何东西。

请您解释一下发生了什么,包括评论中表达的担忧?具体来说,如何指定visibility属性?

0 个答案:

没有答案