我正在尝试编译以下代码,但我收到错误:
模板参数数量错误
template<int start, int end, int step>
struct range{};
template<int start, int end>
struct range<start, end, 1>{};
template<int end>
struct range<0, end, 1>{};
int main() {
auto r1 = range<0, 5, 2>{};
auto r2 = range<5, 15>{}; //error: wrong number of template arguments
auto r3 = range<10>{}; //error: wrong number of template arguments
}
如何创建部分模板类对象?
答案 0 :(得分:4)
您需要根据主模板的声明指定所有模板参数,然后根据模板参数确定选择的参数。
auto r1 = range<0, 5, 2>{}; // the primary template
auto r2 = range<5, 15, 1>{}; // the 1st partial specified template
auto r3 = range<0, 10, 1>{}; // the 2nd partial specified template
如果要指定较少的模板参数,可能需要default template arguments:
template<int end, int start = 0, int step = 1>
struct range{};
auto r1 = range<5, 0, 2>{}; // end->5, start->0, step->2
auto r2 = range<15, 5>{}; // end->15, start->5, step->1
auto r3 = range<10>{}; // end->10, start->0, step->1
请注意,我更改了模板参数的顺序,因为如果为模板参数指定了默认参数,则每个后续模板参数也必须具有默认参数。
答案 1 :(得分:4)
如果您希望能够在start
之前指定end
,还要为start
指定默认参数,则可以执行以下操作:
template <int... Args>
struct range {
static_assert(sizeof...(Args) > 0 && sizeof...(Args) <= 3,
"Must pass 1-3 args");
using ArgPack = std::tuple<std::integral_constant<int, Args>...>;
template <int Size, typename Then, typename Else>
using select_value = typename std::conditional_t<
(sizeof...(Args) > Size), Then, Else
>::type;
static constexpr int start = select_value<1,
std::tuple_element<0, ArgPack>, std::integral_constant<int,0>
>::value;
static constexpr int end = select_value<1,
std::tuple_element<1, ArgPack>, std::tuple_element<0, ArgPack>
>::value;
static constexpr int step = select_value<2,
std::tuple_element<2, ArgPack>, std::integral_constant<int,1>
>::value;
};
这正是您所希望的用法,例如:
int main()
{
using a = range<1,1,2>;
static_assert(a::start == 1 && a::end == 1 && a::step == 2, "wat");
using b = range<1,1>;
static_assert(b::start == 1 && b::end == 1 && b::step == 1, "wat");
using c = range<3>;
static_assert(c::start == 0 && c::end == 3 && c::step == 1, "wat");
}