我希望能夠檢查元程序中使用的類的不變量。我的第一個幼稚的做法是在元編程中強制實現不變量
template <int N>
struct digit
{
static_assert((N >= 0) && (N < 10), "bad invariant");
};
using boom = digit<99>;
但是,這個編譯沒有任何問題。只有在構造非法類時,纔會觸發靜態斷言。
增加額外的模板參數時,它是可能的:
#include <type_traits>
template <int N,
typename = typename std::enable_if<(N >= 0) && (N < 10)>::type>
struct digit;
using crash = digit<-7>;
當我想這種技術適用於作爲一個類型列表類:
#include <type_traits>
template <typename ...> struct are_integral;
template <typename T, typename ...Ts>
struct are_integral<T, Ts...>
{
static const bool value = std::is_integral<T>::value &&
are_integral<Ts...>::value;
};
template <>
struct are_integral<> : std::true_type { };
template <typename ...Ts,
typename = typename std::enable_if<are_integral<Ts...>::value>::type>
struct list;
using ok = list<int, long, char>;
using bad = list<double>;
它根本不工作,因爲海灣合作委員會抱怨,
error: parameter pack 'Ts' must be at the end of the template parameter list struct list;
即使它會工作,類是usel因爲模板參數包不能反映類型列表。
於是,我就用一個「非法」的基類:
template <typename> struct check;
template <typename ...Ts>
struct list : check<typename std::enable_if<are_integral<Ts...>::value>::type>
{ };
using ok = list<int, long, char>;
using bad = list<double>;
這編譯沒有問題。
有什麼辦法可以在C++ 11中完成類似的事情,還是我必須等待概念?
如果您不介意間接性,您可以使用別名模板而不是直接引用「list」模板。不過,我不認爲這是一個很好的解決方案。 – dyp
相關問題我剛纔問:http://stackoverflow.com/questions/11251569/should-static-assert-be-triggered-with--typedef。正如你所看到的,這個問題與模板實例化有關,它儘可能延遲編譯器。目前,我無法想出一種在未明確訪問類成員之一的情況下觸發實例化的方法,但我會繼續思考! –