显式函数专用化的默认模板参数

Default template parameter for explicit function specializations

本文关键字:默认 参数 函数 专用      更新时间:2023-10-16

我想要一组可以接受任何uintX_t变体的函数,而不必复制/粘贴大量代码。到目前为止,我正在尝试使用"标记"来确定要调用的写函数。由于显而易见的原因,T = unsigned不起作用,因为我可能有uint32_tuint16_t

struct number_tag {};
struct hexadecimal : number_tag {};
struct number : number_tag {};
template <typename T = unsigned, typename Tag>
void write(T t);

然后稍后在.cpp文件中:

template <>
void write<unsigned, hexadecimal>(unsigned num)
{
}
template <>
void write<unsigned, number>(unsigned num)
{
}

理想情况下,我想这样称呼它:

write<number>(10);
write("n");
write<hexadecimal>(0xFF);

我该如何写这篇文章,这样我就不必做write<unsigned, number>,也不必为每个uintX_t变体创建一堆专业化?

不能部分专门化函数(boo),但可以使用更多无用的结构!

struct number_tag {};
struct hexadecimal : number_tag {};
struct number : number_tag {};
template <typename Tag, typename T = unsigned>
struct Writer;
template <typename T>
struct Writer<hexadecimal, T>
{
    static void write(T num) {}
};
template <typename T>
struct Writer<number, T>
{
    static void write(T num) {}
};
template <typename Tag, typename T = unsigned>
void write(T t)
{
    Writer<Tag, T>::write(t);
}
int main()
{
    write<number>(10);
    write<hexadecimal>(0xFF);
}

如果您想根据tag使用单独的write专用化,则添加重载(因为函数不能部分专用化):

template <typename T = unsigned>
void write(T t, hexadecimal tag)
{
}
template <typename T = unsigned>
void write(T t, number tag)
{
}
template <typename Tag, typename U = unsigned>
void write(U num)
{
    write<U>(num, Tag{});
}
write<number>(10);
write<hexadecimal>(0xFF);
write<number, std::uint16_t>(0xFF);

演示


如果您想为函数添加一个约束,使其只接受无符号整数类型,下面的代码会进行正确的验证:

template <typename Tag, typename U = unsigned>
auto write(U num) -> typename std::enable_if<std::is_unsigned<U>::value, void>::type
{
    write<U>(num, Tag{});
}
write<number>(10u);
//write<number>(-1); // triggers error

演示2

注意:当前声明template <typename T = unsigned> void write(T t);不会强制类型为unsigned,因为编译器会根据实际参数的类型推导出参数的类型。


如果要强制传递给write函数的任何类型unsigned,可以使用以下代码:

template <typename Tag, typename U>
void write(U num)
{
    write<typename std::make_unsigned<U>::type>(num, Tag{});
}
write<number>(-1); // gets converted to unsigned type

演示3