【发布时间】:2017-08-13 20:27:40
【问题描述】:
我正在尝试使用成员函数string() 将boost::filesystem::path 的向量转换为std::string。我写了这个,它在 Windows 上运行良好(MSVC 14, 2015):
std::transform(
users.begin(), users.end(), std::back_inserter(usersStrs),
std::mem_fn(static_cast<const std::string (PathType::*)() const>(
&PathType::string)));
现在我转到 gcc(6.3,Debian Stretch),我的代码给出了链接错误,上面的签名不存在。为了修复它,我不得不将代码更改为:
std::transform(
users.begin(), users.end(), std::back_inserter(usersStrs),
std::mem_fn(static_cast<const std::string& (PathType::*)() const>(
&PathType::string)))
PS:我知道 lambda 解决方案更简单,我现在切换到了,出于必要。
起初,我认为 MSVC 更宽容,但后来我切换回 Windows 并得到相反的链接错误,第一个签名是正确的。我去了源代码(1.64,path.hpp),发现是这样的:
# ifdef BOOST_WINDOWS_API
const std::string string() const
{
std::string tmp;
if (!m_pathname.empty())
path_traits::convert(&*m_pathname.begin(), &*m_pathname.begin()+m_pathname.size(),
tmp);
return tmp;
}
//...
# else // BOOST_POSIX_API
// string_type is std::string, so there is no conversion
const std::string& string() const { return m_pathname; }
//...
# endif
所以我看到的原因是,在 Windows 上,因为它默认不使用 UTF-8,所以有一个临时转换。但是为什么 boost 不对 Windows 和 Linux 使用相同的 API 呢?最坏的情况是,它会花费一个字符串的副本。对吧?
我应该使用 path::string() 的替代品来获得跨平台 API 稳定性吗?
【问题讨论】:
-
为什么你首先需要
static_cast<>? -
@Frank 没有它就无法工作,因为
path::string()的重载具有不同的签名。必须定义要使用的签名。 -
可能是因为在 Windows 上路径存储为 2 字节 UTF-16 宽字符,因此需要转换为 ::std::string,而在 Linux 上它存储为 utf-8 字符?我的意思是这种特定转换方法的权衡比每次执行某些路径操作时来回转换字符串的权衡要好?
-
@VTT 对不起,我想我已经在问题中提到了。
-
@Phil1970:恰恰相反;除非确实有必要,否则优化不应妨碍一致的 API。此外,函数签名几乎从来都不是实现细节——它是库和用户之间契约的一部分。
标签: c++ linux c++11 boost boost-filesystem