我有一个使用Boost进行base 64编码的函数。它需要两个模板参数:一个用于输入的容器类型,一个用于输出的容器类型。这允许您执行诸如使用std::vector
提供二进制数据但返回std::string
之类的事情。
以下是代码:
template<typename OutputContainer, typename InputContainer>
OutputContainer Encode(InputContainer const& data)
{
using namespace boost::archive::iterators;
using base64_it = base64_from_binary<transform_width<
typename InputContainer::const_iterator, 6, 8>>;
OutputContainer result(base64_it(data.begin()), base64_it(data.end()));
static std::string const padding[] { "", "==", "="};
auto const& pad = padding[data.size() % 3];
result.insert(result.end(), pad.begin(), pad.end());
return result;
}
用法示例:
std::string data = "Hello World!+";
auto encoded = Encode<std::string>(data);
实时样本here
请注意,在上面的示例中,我仍然必须为输出容器提供模板参数,即使它与输入容器的类型相同。在这些情况下,我希望OutputContainer
模板参数是可选的,而是使用InputContainer
推导出的类型。我不确定我可以通过哪种解决方法或调整来获得这种界面,但是很高兴看到SO社区可以提出什么。
注意我也对更加以迭代器为中心的方法持开放态度,但由于冗余/样板(我认为传递容器比迭代器更简单),我避免使用它。如果它看起来像std::transform()
的4参数版本,我想我对解决方案不太满意。
答案 0 :(得分:4)
对于InputContainer
和OutputContainer
相同的情况使用重载(非专业化),enable_if
在这种情况下禁用原始实现,它可能实现你所要求的。需要注意的是,除非同时提供第三个参数,否则将无法再明确指定两种容器类型:
template<typename OutputContainer, typename InputContainer, typename = std::enable_if_t<!std::is_same_v<OuptputContainer, InputContainer>>>
OutputContainer Encode(InputContainer const& data)
{
// Your implementation
}
template<typename OutputContainer>
OutputContainer Encode(OutputContainer const& data)
{
return Encode<OutputContainer, OutputContainer, void>(data);
}