[英]Variadic template overload resolution
假設我有一個可以遞增的模板參數列表。 我想增加這個列表的頭部。 這是代碼
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
首先,編寫代碼來進行操作List<>
代替裸variardic類型列表,它會更容易。
其次,不使用模板函數,而是使用模板類。
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;
};
和類似的。 請注意,我對類型進行操作,我專門從傳遞給一個類型的一些通用variardic包生產類型template
-這意味着我不依賴於一個方式合作,variardic ARGS打包成一個單一的類型。
我也寫template
別名,以減少typename
垃圾郵件。
接下來,應用仿函數:
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...>>();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.