2015-08-28 64 views
5

我可以創建只接受指向一個可變參數模板:創建可變參數只接受引用或指針

template<typename ... Types> 
void F(Types *... args); 

或者只接受引用一個可變參數模板:

template<typename ... Types> 
void F(Types &... args); 

如何創建一個模板它接受非const引用還是指針?
例如

int a, b, c; 
F(a, &b); // => F<int &, int *> 
F(a, 3); // Error, 3 not pointer and cannot bind to non const-reference 

注:參考版本看起來OK的,因爲它可以綁定到指針引用,但它不是因爲它不會綁定到int * const

+1

我認爲你應該接受通用的'類型...'然後通過像'的std :: is_pointer' –

+0

@PaoloM檢查他們的幸福指針或引用:第一個例子不會有效。 – Dani

回答

6

我們可以寫一個特性來檢查類型是一個指針或一個非const引用:

template <typename T> 
using is_pointer_or_ref = 
    std::integral_constant<bool, std::is_pointer<T>::value || 
    (std::is_lvalue_reference<T>::value && 
    !std::is_const<typename std::remove_reference<T>::type>::value)>; 

然後,我們可以寫一個特點使用Jonathan Wakely's and_檢查這在參數包:

template<typename... Conds> 
    struct and_ 
    : std::true_type 
    { }; 

template<typename Cond, typename... Conds> 
    struct and_<Cond, Conds...> 
    : std::conditional<Cond::value, and_<Conds...>, std::false_type>::type 
    { }; 

template <typename... Ts> 
using are_pointer_or_ref = and_<is_pointer_or_ref<Ts>...>; 

現在我們可以使用std::enable_if驗證類型:

template<typename ... Types, 
    typename std::enable_if<are_pointer_or_ref<Types...>::value>::type* = nullptr> 
void F(Types&&... args){} 

請注意,轉發引用對於檢測參數的值類別是必要的,以便引用檢查可以正常工作。

Live Demo

+0

*轉發引用*您的意思是*通用引用*即「類型&&」? –

+1

@PaoloM是的,但我相信「轉發參考」是[現在的首選詞](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4164.pdf)。 – TartanLlama

+0

如果Bjarne這麼說......謝謝;) –

1

你可以簡單地檢查每個類型的要求在Args - 例如正是如此:

// Helper templates 
template <bool...> struct bool_pack {}; 
template <bool b, bool... rest> 
struct all_of : std::is_same<bool_pack<b, rest...>, bool_pack<rest..., b>> {}; 

template <typename... Args> 
auto F(Args&&... args) 
    -> std::enable_if_t<all_of<std::is_lvalue_reference<Args>{} 
          or std::is_pointer<std::decay_t<Args>>{}...>{}> 
{} 

假設F用於與扣只,僅左值和指針將被允許。用你的例子Demo

+0

我想你需要檢查被引用的類型是否被標記爲'const',因爲這將允許使用'const int a; F(a);' – TartanLlama

+0

@TartanLlama我認爲他的意圖是不允許rvalues。 – Columbo

+0

啊,你可能是對的。無論如何,如果OP想要創建一個,這是一個簡單的解決辦法。 – TartanLlama