我有很多混合的东西,它们都会导致未定义的引用。请原谅我删除代码,但是,由于我不知道哪些是个别问题,我无法搜索它们。
// 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>;
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属性?