【发布时间】:2018-04-07 02:32:28
【问题描述】:
我目前正在尝试制作一个名为MakeByte 的可变参数模板函数,它将接受任意数量的位参数,并将它们放入一个字节中。这是它的用法示例:
// The Wii U has 4 RAM chips, here we select a seemingly "random" one using an
// algorithm to generate one from the coordinates.
quint32 bank_bit_0 = Bit((y / (16 * m_num_pipes)) ^ x_3);
quint32 bank_bit_1 = Bit((y / (8 * m_num_pipes)) ^ x_4);
quint32 bank = MakeByte(bank_bit_0, bank_bit_1);
我有三个函数,在一个单独的标题中涉及:
-
template <typename T1, typename... T2> T1 MakeByte(T1 bit, T2... bits),调用递归函数的外部代码将使用的函数。 -
template <typename T1, typename... T2> T1 MakeByte(T1 byte, quint32 pos, T1 bit, T2... bits),遍历每一位的递归函数。这个函数有额外的参数来跟踪最后一个字节,以及放置下一个位的当前位置。 -
template <typename T1, typename T2> T1 MakeByte(T1 byte, quint32 pos, T2 bit),处理最后一位的函数。
这是完整的 3 个定义:
template <typename T1, typename T2>
constexpr T1 MakeByte(T1 byte, quint32 pos, T2 bit)
{
return byte | (bit << pos);
}
template <typename T1, typename... T2>
constexpr T1 MakeByte(T1 byte, quint32 pos, T1 bit, T2... bits)
{
return MakeByte(byte | (bit << pos), pos + 1, bit, bits...);
}
template <typename T1, typename... T2>
constexpr T1 MakeByte(T1 bit, T2... bits)
{
return MakeByte(static_cast<T1>(0), 0, bit, bits...);
}
问题是,当用 g++ 编译时,我得到这个错误:
/home/kyle/Documents/Projects/C++/Qt/MK8Studio/Source/Common.h:44: error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
return MakeByte(static_cast<T1>(0), 0, bit, bits...);
~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
此时,我重命名了两个递归函数,以防有歧义:
template <typename T1, typename T2>
constexpr T1 MakeByte_(T1 byte, quint32 pos, T2 bit)
{
return byte | (bit << pos);
}
template <typename T1, typename... T2>
constexpr T1 MakeByte_(T1 byte, quint32 pos, T1 bit, T2... bits)
{
return MakeByte_(byte | (bit << pos), pos + 1, bit, bits...);
}
template <typename T1, typename... T2>
constexpr T1 MakeByte(T1 bit, T2... bits)
{
return MakeByte_(static_cast<T1>(0), 0, bit, bits...);
}
这段代码确实可以编译,但我不禁觉得这有点骇人听闻。从设计的角度来看,在可变参数模板函数中减少歧义的最佳方法是什么?
【问题讨论】:
-
没有消除歧义的通用“最佳方法”。每个人的情况都会根据自己的优点来解决。单独的解决方案可能涉及以下技术:重命名;使用
std::enable_if;或作为部分特化模板函数的变通方法调用的部分特化模板类。没有一种尺寸适合所有人。 -
什么是
quint32?这很重要,因为我怀疑int可能是您的问题。 -
@Yakk 它只是一个无符号整数的 typedef。
标签: c++ c++11 templates recursion variadic-templates