我有一个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)。我以特殊方式处理某些类型(例如,字符串忽略空终止符),这就是为什么我有这么多的重载。
数组模板更适合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)
| 归档时间: |
|
| 查看次数: |
64 次 |
| 最近记录: |