为容器中的不同字符串类型实现编译时"static-if"逻辑

Mr.*_*C64 12 c++ containers templates compile-time c++11

我想编写一个函数模板,对一个字符串容器进行操作,例如a std::vector.

我想支持两者CStringstd::wstring使用相同的模板功能.

问题是,CStringwstring有不同的接口,例如获取a的"长度" CString,你调用GetLength()方法,而不是你调用的wstring size()length().

如果我们在C++中有一个"静态if"功能,我可以这样写:

template <typename ContainerOfStrings>
void DoSomething(const ContainerOfStrings& strings)
{
    for (const auto & s : strings)
    {
        static_if(strings::value_type is CString) 
        {
            // Use the CString interface
        }
        static_else_if(strings::value_type is wstring)
        {   
            // Use the wstring interface
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

是否有一些模板编程技术可以使用当前可用的C++ 11/14工具实现这一目标?

PS
我知道可以DoSomething()vector<CString>和编写几个重载vector<wstring>,但这不是问题的关键.
此外,我希望这个函数模板适用于任何可以使用range-for循环进行迭代的容器.

Pio*_*cki 19

#include <type_traits>

template <typename T, typename F>
auto static_if(std::true_type, T t, F f) { return t; }

template <typename T, typename F>
auto static_if(std::false_type, T t, F f) { return f; }

template <bool B, typename T, typename F>
auto static_if(T t, F f) { return static_if(std::integral_constant<bool, B>{}, t, f); }

template <bool B, typename T>
auto static_if(T t) { return static_if(std::integral_constant<bool, B>{}, t, [](auto&&...){}); }
Run Code Online (Sandbox Code Playgroud)

测试:

template <typename ContainerOfStrings>
void DoSomething(const ContainerOfStrings& strings)
{
    for (const auto & s : strings)
    {
        static_if<std::is_same<typename ContainerOfStrings::value_type, CString>{}>
        ([&](auto& ss)
        {
            // Use the CString interface
            ss.GetLength();
        })(s);

        static_if<std::is_same<typename ContainerOfStrings::value_type, wstring>{}>
        ([&](auto& ss)
        {
            // Use the wstring interface
            ss.size();
        })(s);
    }
}
Run Code Online (Sandbox Code Playgroud)

DEMO


Sme*_*eey 6

您可以提供满足您需要的功能重载:

size_t getSize(const std::string& str)
{
    return str.size();
}

size_t getSize(const CString& str)
{
    return str.GetLength();
}

template <typename ContainerOfStrings>
void DoSomething(const ContainerOfStrings& strings)
{
    for (const auto & s : strings)
    {
        ...
        auto size = getSize(s);
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)