针对模板的过时显式实例化进行编译
Compile against a outdated explicit instantiation of a template
我使用一个库 (Orocos),它定义了自己的 std::basic_string
和自定义分配器。此外,它显式实例化它:
namespace RTT
{
typedef std::basic_string<char, std::char_traits<char>, RTT::os::rt_allocator<char> > rt_string;
}
namespace std
{
extern template class basic_string<char, char_traits<char>, RTT::os::rt_allocator<char> >;
}
在我切换到 C++17 之前,它运行良好。在 C++ 17 中,std::basic_string
有新函数,即 data()
的非 const 版本。现在,当我编译时,我得到了对 RTT::rt_string::data()
的未定义引用,因为 Orocos 不知道 C++17。
最“正确”的事情是什么?
- 修补库以至少编译 C++17 中的模板实例化。
- 修补库以不显式实例化此 class。
- 不要使用那些方法。我可以应付,但每次我在非常量对象上使用该方法时,我都必须做类似
const_cast<RTT::rt_string const&>(myString).data()
的事情。另外,如果我忘记了,我会再次出现奇怪的链接器错误。
- 以某种方式将这些符号添加到我的库中。
data()
是一个隐式内联函数,如果我在发布时编译问题应该消失了。不是真正的解决方案。
您应该能够为缺少的成员函数添加显式实例化定义到您自己的代码中(仅在一个源文件中):
template char* std::basic_string<char, std::char_traits<char>, RTT::os::rt_allocator<char> >::data() noexcept;
这并不严格符合标准库中的成员函数签名,但同时使用两种语言版本已经超出了标准的正式范围(并且使用两种不同的语言版本将违反 ODR以这种方式定义的任何程序版本 class(模板))。
我使用一个库 (Orocos),它定义了自己的 std::basic_string
和自定义分配器。此外,它显式实例化它:
namespace RTT { typedef std::basic_string<char, std::char_traits<char>, RTT::os::rt_allocator<char> > rt_string; } namespace std { extern template class basic_string<char, char_traits<char>, RTT::os::rt_allocator<char> >; }
在我切换到 C++17 之前,它运行良好。在 C++ 17 中,std::basic_string
有新函数,即 data()
的非 const 版本。现在,当我编译时,我得到了对 RTT::rt_string::data()
的未定义引用,因为 Orocos 不知道 C++17。
最“正确”的事情是什么?
- 修补库以至少编译 C++17 中的模板实例化。
- 修补库以不显式实例化此 class。
- 不要使用那些方法。我可以应付,但每次我在非常量对象上使用该方法时,我都必须做类似
const_cast<RTT::rt_string const&>(myString).data()
的事情。另外,如果我忘记了,我会再次出现奇怪的链接器错误。 - 以某种方式将这些符号添加到我的库中。
data()
是一个隐式内联函数,如果我在发布时编译问题应该消失了。不是真正的解决方案。
您应该能够为缺少的成员函数添加显式实例化定义到您自己的代码中(仅在一个源文件中):
template char* std::basic_string<char, std::char_traits<char>, RTT::os::rt_allocator<char> >::data() noexcept;
这并不严格符合标准库中的成员函数签名,但同时使用两种语言版本已经超出了标准的正式范围(并且使用两种不同的语言版本将违反 ODR以这种方式定义的任何程序版本 class(模板))。