假设我有一个可以递增的模板参数列表。我想增加这个列表的头。以下是代码
template<int N>
struct Counter {
static constexpr Counter<N+1> increment();
};
template<int N>
constexpr Counter<N+1> Counter<N>::increment() {
return Counter<N+1>();
}
//List (will be used as List of Counters)
template <typename... TAIL>
struct List {};
template <typename HEAD, typename... TAIL>
struct List<HEAD,TAIL...> {};
template <typename HEAD, typename... TAIL>
auto incrFront() -> decltype(List<decltype(HEAD::increment()),TAIL...>()) {
return List<decltype(HEAD::increment()),TAIL...>();
}它确实在起作用:
auto l0 = incrFront<Counter<0>>(); // Ok, decltype(l0) == List<Counter<1>>
l0 = List<Counter<1>>(); //Ok, right type
auto l1 = incrFront<Counter<0>,Counter<1>>(); // Ok, decltype(l1) == List<Counter<1>,Counter<1>>
l1 = List<Counter<1>,Counter<1>>();现在,我想增加列表的后面,所以
template <typename... HEAD, typename TAIL>
auto incrBack() -> decltype(List<decltype(HEAD...,TAIL::increment())>()) {
return List<decltype(HEAD...,TAIL::increment()>();
}但出现错误“”incrBack“”未在此范围内声明
我尝试在这个方法之前添加另一个方法:
template <typename... HEAD>
auto incrBack() -> decltype(List<HEAD...>()) {
std::cout << "Should not be here\n";
return List<HEAD...>();
}希望这个方法在解决重载时永远不会被调用,但是这个方法确实被调用了。
有什么线索吗?我只想让这个例子起作用:
auto l2 = incrBack<Counter<1>,Counter<1>>(); // I want decltype(l2) == List<Counter<1>,Counter<2>>
l2 = incrFront<Counter<0>,Counter<2>>(); //should be possible发布于 2013-05-21 21:47:44
首先,编写在List<>上操作的代码,而不是裸露的变量类型列表,这样会更容易。
其次,不要使用模板函数,而要使用模板类。
template<typename T>
struct inc {
typedef decltype(T::increment()) type;
};
template<typename T>
using Inc = typename inc<T>::type;现在,我们可以讨论Inc<HEAD>而不是decltype( HEAD::increment() ),这将使您的代码更具可读性。
编写以下template类:
template<typename List, typename T>
struct append;
template<typename List, typename T>
using Append = typename append<List,T>::type;
template<template<typename...>class TypeList, typename... Ts, typename T>
struct append<TypeList<Ts...>, T> {
typedef TypeList<Ts..., T> type;
};
template<typename List>
struct reverse;
template<typename List>
using Reverse = typename reverse<List>::type;
template<template<typename...>class TypeList>
struct reverse<TypeList<>> {
typedef TypeList<> type;
};
template<template<typename...>class TypeList, typename T0, typename... Ts>
struct reverse<TypeList<T0, Ts...>> {
typedef Append< Reverse<TypeList<Ts...>>, T0 > type;
};和类似的。请注意,我对类型进行操作,并且我专门处理从传递给template的一些泛型变量包生成的类型--这意味着我不会局限于使用一种方法将变量参数打包到单个类型中。
为了减少typename垃圾邮件,我还编写了template别名。
接下来,应用functor:
template<template<typename>class Func, typename List>
struct apply_to_first;
template<template<typename>class Func, typename List>
using ApplyToFirst = typename apply_to_first<Func, List>::type;
template<template<typename>class Func, template<typename...>class TypeList, typename T0, typename... Ts>
struct apply_to_first<Func, TypeList<T0, Ts...>> {
typedef TypeList< typename Func<T0>::type, Ts... > type;
};然后是IncFirst
template<typename List>
using IncFirst = ApplyToFirst< inc, List >;现在已经很短了。
至于IncLast,它稍微更难一些:
template<typename List>
using IncLast = Reverse< IncFirst < Reverse<List> > >;但仍然只有一条线。尽管如此,我更喜欢这个更详细的版本:
template<template<typename>class Func, typename List>
using ApplyToLast = Reverse< ApplyToFirst< Func, Reverse<List> > >;
template<typename List>
using IncLast = ApplyToLast< inc, List >;现在,我没有直接回答你的问题,因为我从来没有写过incrFront (我也没有编译上面的代码,所以它可能充满了语法错误)。
因此,在将繁重的工作转移到上面的迷你元编程库之后,下面是incrFirst和incrLast:
template<typename... Ts>
IncFirst<List<Ts...>> incrFirst() {
return IncFirst<List<Ts...>>();
}
template<typename... Ts>
IncLast<List<Ts...>> incrLast() {
return IncLast<List<Ts...>>();
}https://stackoverflow.com/questions/16670260
复制相似问题