使第一个模板参数可选

时间:2018-03-29 13:30:21

标签: c++

我有一个使用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参数版本,我想我对解决方案不太满意。

1 个答案:

答案 0 :(得分:4)

对于InputContainerOutputContainer相同的情况使用重载(非专业化),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);
}

Example on Godbolt