假设我要创建以下类:
#pragma once
#include <memory>
#include <string>
namespace stackquestion
{
struct Logger
{
void Log(std::string message);
private:
class Impl;
std::unique_ptr<Impl> impl;
};
}
当我要发布类时,最终取决于我的消费者定义std::string
和std::unique_ptr
。我对发布的含义含糊不清。我正在考虑将某人交给一个库进行静态或动态链接。
当我退回没有这些版本的版本时,我最终会失去想要获得的舒适性/安全性。
#pragma once
namespace stackquestion
{
struct Logger
{
void Log(const char *);
private:
class Impl * impl;
};
}
我缺少银弹吗?
答案 0 :(得分:1)
两种解决方案都可以,这取决于您的目标。
这样做,不会破坏代码,您确实迫使他们使用C ++ 11或更高版本来使用您的库。但是,我认为这是一个加分点,因为您不必弄乱许多支持C ++ 98的技巧。
在编译代码时,它们不应与标准库混淆,因此,如果它们执行#defined unique_ptr shared_ptr
之类的事情,我会责怪您的用户编码错误,而不是您。是的,您可以尝试避免用户做很多坏事,例如重载operator&
(的地址),但是,您最终会得到类似于STL实现的代码,
使用丘疹可以解决上述许多问题。但是,因此您不应该使用它。 pimple的唯一真正优势是二进制兼容性。
由于您没有公开STL或除您自己的库以外的任何其他库,因此不应在std::string
上遇到链接错误。 (是的,这是可能的)
如果您使用libc++
编译库,则std::string
实际上是std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >
,具有专用于libcxx的内存布局。
如果您使用libstdc++
编译库,则std::string
会变成std::basic_string<char, std::char_traits<char>, std::allocator<char> >
(或C ++ 11变体的更长名称)
有关更多详细信息,请参见this thread