如果全部啟用,則啟用
Version >= C++ 11
勵志的例子
在模板引數列表中有可變引數模板包時,如下面的程式碼片段所示:
template<typename ...Args> void func(Args &&...args) { //... };
標準庫(在 C++ 17 之前)沒有直接的方法來編寫 enable_if 來對 Args
中的所有引數或 Args
中的任何引數施加 SFINAE 約束。C++ 17 提供了 std::conjunction
和 std::disjunction
來解決這個問題。例如:
/// C++17: SFINAE constraints on all of the parameters in Args.
template<typename ...Args,
std::enable_if_t<std::conjunction_v<custom_conditions_v<Args>...>>* = nullptr>
void func(Args &&...args) { //... };
/// C++17: SFINAE constraints on any of the parameters in Args.
template<typename ...Args,
std::enable_if_t<std::disjunction_v<custom_conditions_v<Args>...>>* = nullptr>
void func(Args &&...args) { //... };
如果你沒有可用的 C++ 17,有幾種解決方案可以實現這些目標。其中之一是使用基本案例類和部分特化,如本問題的答案所示。
或者,也可以用相當直接的方式手工實現 std::conjunction
和 std::disjunction
的行為。在下面的例子中,我將演示實現並將它們與 std::enable_if
組合以產生兩個別名:enable_if_all
和 enable_if_any
,它們完全按照它們的語義進行操作。這可以提供更具伸縮性的解決方案。
**** enable_if_all
和 enable_if_any
的實施
首先讓我們分別使用自定義的 seq_and
和 seq_or
來模擬 std::conjunction
和 std::disjunction
:
/// Helper for prior to C++14.
template<bool B, class T, class F >
using conditional_t = typename std::conditional<B,T,F>::type;
/// Emulate C++17 std::conjunction.
template<bool...> struct seq_or: std::false_type {};
template<bool...> struct seq_and: std::true_type {};
template<bool B1, bool... Bs>
struct seq_or<B1,Bs...>:
conditional_t<B1,std::true_type,seq_or<Bs...>> {};
template<bool B1, bool... Bs>
struct seq_and<B1,Bs...>:
conditional_t<B1,seq_and<Bs...>,std::false_type> {};
然後實現非常簡單:
template<bool... Bs>
using enable_if_any = std::enable_if<seq_or<Bs...>::value>;
template<bool... Bs>
using enable_if_all = std::enable_if<seq_and<Bs...>::value>;
最後一些助手:
template<bool... Bs>
using enable_if_any_t = typename enable_if_any<Bs...>::type;
template<bool... Bs>
using enable_if_all_t = typename enable_if_all<Bs...>::type;
用法
用法也很簡單:
/// SFINAE constraints on all of the parameters in Args.
template<typename ...Args,
enable_if_all_t<custom_conditions_v<Args>...>* = nullptr>
void func(Args &&...args) { //... };
/// SFINAE constraints on any of the parameters in Args.
template<typename ...Args,
enable_if_any_t<custom_conditions_v<Args>...>* = nullptr>
void func(Args &&...args) { //... };