该问题与重复的相关问题不同-这是为了避免众所周知的解决方案,该解决方案将所有类显式实例化为.cpp文件中的模板参数,并将声明保留在标头中。使用CRTP可以通过在CRTP:CRTP()构造函数中声明应在.cpp文件中添加的内容相同,来简化此过程,但不要将其添加到每个.cpp文件中,所需的派生类应仅继承CRTP。
尝试在Clang中实现CRTP时出现链接错误(使用MVSC可以正常工作):
struct IPersistStream {
~IPersistStream() {}
enum Direction {
Read,
Write
};
};
template <class Derived>
struct CRTP
{
CRTP()
{
auto _dummy_Read = &Derived:: template Persist<IPersistStream::Read>;
auto _dummy_Write = &Derived:: template Persist<IPersistStream::Write>;
_dummy_Read; _dummy_Write;
}
};
这是派生类:
class DerivedClass: public CRTP<DerivedClass>
{
public:
template <int direction>
ErrorCode Persist(void *p, size_t sz);
};
实际的Persist函数的实现位于.cpp文件中,而声明位于.h文件中,因此链接程序会抱怨它们未解决。
起初,当我使用Derived :: Persist时,我也遇到了编译错误(MSVC也很好用),但是两者之间的 template 键区(类似于。和。 ->用法)解决了编译问题。
以下内容并未链接,就像MSVC一样:
1>Link : error : L0039: reference to undefined symbol `char const* DerivedClass::Persist<0>(PersistStream<0>&)' in file "DerivedClass.o"
1>Link : error : L0039: reference to undefined symbol `char const* DerivedClass::Persist<1>(HSL::PersistStream<1>&)' in file "DerivedClass.o"
有人建议为什么设计用于解决链接问题的模式实际上在MSVC中有效,而在Clang中不起作用?
谢谢