具有数组类型的模板重载:强制char数组使用string_view

voi*_*ter 2 c++ c++17

我有一个print()重载的模板方法来处理不同的类型。我关心的三个类别:

  • 标量值的数组类型,不包括文字字符串(例如unsigned foo[5]
  • 字符串文字(例如"Hello World"
  • 字符串类型(char const*std::string

第一项应与字符串处理不同(后两点)。这是我编写的一些代码,试图区分它们(LIVE SAMPLE):

template<typename Container, typename T,
    std::enable_if_t<std::is_pod_v<T> && !std::is_pointer_v<T> && !std::is_array_v<T>, int> = 0>
void print(T const&)
{
    std::cout << "Generic Value\n";
}

template<typename Container, typename Array, std::size_t Size>
void print(Array const (&)[Size])
{
    std::cout << "Array\n";
}

template<typename Container>
void print(std::string_view)
{
    std::cout << "String View\n";
}

int main()
{
    { // GOOD: Uses string_view
        char const* value = "Hello";
        print<int>(value);
    }
    { // GOOD: Uses string_view
        std::string value = "value";
        print<int>(value);
    }
    { // GOOD: Uses array overload
        unsigned value[] = {1, 2, 3};
        print<int>(value);
    }
    { // BAD: Should use the string_view overload
        print<int>("Hello");
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到的输出:

String View
String View
Array
Array
Run Code Online (Sandbox Code Playgroud)

请注意标有的情况BAD。我希望这可以由处理string_view,但是因为从技术上讲它是一个数组,所以不是。我想我可以通过执行enable_ifwith is_same来检查(并排除)参数的char类型来解决此问题Array,但这似乎有点麻烦。

有没有更容易管理的方式为这些类型进行通用编程?本质上,我想将字符串作为字符串处理(主要是因为使用null终止符),而将非字符串作为数据的原始字节处理。

一些上下文/注释:

该示例使用了Container毫无意义的模板参数。这只是强制所有功能为模板。在我的真实代码中,这是一个有意义的模板参数(实际上是指一个STL容器,传递的值将被写入一系列字节)。同样print,我实际代码中的方法实际上是重载<<运算符。我真正的代码的全部要点是将各种类型的二进制数据写入容器(如二进制数据的iostream)。我以特殊方式处理某些类型(例如,字符串忽略空终止符),这就是为什么我有这么多的重载。

rus*_*tyx 5

数组模板更适合char[]类型,因为string_view版本涉及用户定义的转换。

您可以char[]使用SFINAE 禁用类型的数组版本:

template<typename Container, typename Array, std::size_t Size,
    std::enable_if_t<!std::is_same_v<Array, char>, int> = 0>
void print(Array const (&)[Size])
{
    std::cout << "Array\n";
}
Run Code Online (Sandbox Code Playgroud)

或实现其他代理重载:

template<typename Container, std::size_t Size>
void print(char const (&s)[Size])
{
    print<Container>(std::string_view(s));
}
Run Code Online (Sandbox Code Playgroud)