3

我試圖構建一個可變模板類。通常情況下,實例化的每個級別需要通過切分一個類型然後使用餘數來實例化「下一級」。對於我的最後一個層次,而不是專門研究一種類型,我寧願提供一些基本的案例類型,並避免重複實際的邏輯。std :: conditional的模板化差異使用,其中一種類型是實例化故障

我添加了std::conditional來打開BaseCase,其餘的類型由一個空的參數包組成。

class BaseCase { }; 

template <typename T, typename... Ts> 
class VariadicClass; 

template <typename... Ts> 
using NextLevel = typename std::conditional< 
    sizeof...(Ts) != 0, VariadicClass<Ts...>, BaseCase>::type; 

template <typename T, typename... Ts> 
class VariadicClass { 
    T this_level; // whatever 
    NextLevel<Ts...> next_level; // fails when Ts is empty 
}; 

問題VariadicClass上的至少一種類型參數模板,所以當它擊中基礎案例(Ts爲空),試圖使用std::conditional使用VariadicClass<>,這當然會失敗。

我管理的解決方案是編寫一些特定的功能,並使用decltype以及重載,根本不使用std::conditional

template <typename... Ts> 
VariadicClass<Ts...> type_helper(Ts&&...); 

BaseCase type_helper(); 

template <typename... Ts> 
using NextLevel = decltype(type_helper(std::declval<Ts>()...)); 

現在,這個工作,但如果我想每次有一個可變類,我想要保持這種做法,這似乎很乏味。有沒有辦法使用std::conditional或類似的東西來實現這種效果,而不必寫出太多問題特定的代碼?

回答

4

推遲評價。

template<class T>struct identity{ 
    template<class...>using result=T; 
}; 
template<template<class...>class src> 
struct delay{ 
    template<class...Ts>using result=src<Ts...>; 
}; 

template <typename... Ts> 
using NextLevel = 
typename std::conditional< 
    sizeof...(Ts) != 0, delay<VariadicClass>, identity<BaseCase> 
>::type::template result<Ts...>; 

identity忽略Ts...和返回它的參數。 delay需要template並應用Ts...。雖然簽名看起來很可疑,但它起作用。

4

爲什麼不

class BaseCase { }; 

template <typename... Ts> 
class VariadicClass; // undefined base template 

template <typename... Ts> 
using NextLevel = typename std::conditional< 
    sizeof...(Ts) != 0, VariadicClass<Ts...>, BaseCase>::type; 

template <typename T, typename... Ts> 
class VariadicClass<T, Ts...> { // partial specialization for having at least 1 type parameter 
    T this_level; // whatever 
    NextLevel<Ts...> next_level; 
}; 
+0

你也可以實現'BaseCase'作爲'VariardicClass <>'專業化,完全擺脫'NextLevel'。 – Yakk 2014-08-28 15:59:03

0

或者,你可以專注VariadicClass<T>

class BaseCase {}; 

// general case 
template <typename T, typename... Ts> 
class VariadicClass { 
    T this_level; // whatever 
    VariadicClass<Ts...> next_level; 
}; 

// specialization 
template <typename T> 
class VariadicClass<T> { 
    T this_level; // whatever 
    BaseClass next_level; 
}; 
+0

這是我試圖避免做的事情 – 2014-08-28 15:20:24

2

閱讀T.C.'s answer和Yakk的評論後,我意識到我可以用兩個專業寫爲一個模板類,而不是寫另一BaseClass和類型別名。

template <typename... Ts> 
class VariadicClass; 

// specialization gets everything but an empty Ts 
template <typename T, typename... Ts> 
class VariadicClass<T, Ts...> { 
    VariadicClass<Ts...> next_level; 
    // normal case 
}; 

template <> 
class VariadicClass<> { // instead of class BaseCase 
    // base case 
};