显式函数特化的默认模板参数

时间:2014-09-13 12:23:27

标签: c++ templates specialization

我希望有一组函数可以接受任何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变体创建一系列特化?

2 个答案:

答案 0 :(得分:3)

你不能部分专门化功能(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);
}

答案 1 :(得分:1)

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

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);

DEMO


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

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

DEMO 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

DEMO 3