2016-03-07 51 views
2

給定一個(降低)實現的detection idiom我們可以使用檢測成語來檢查一個類是否具有特定簽名的成員函數?

namespace type_traits 
{ 
    template<typename... Ts> 
    using void_t = void; 

    namespace detail 
    { 
     template<typename, template<typename...> class, typename...> 
     struct is_detected : std::false_type {}; 

     template<template<class...> class Operation, typename... Arguments> 
     struct is_detected<void_t<Operation<Arguments...>>, Operation, Arguments...> : std::true_type {}; 
    } 

    template<template<class...> class Operation, typename... Arguments> 
    using is_detected = detail::is_detected<void_t<>, Operation, Arguments...>; 

    template<template<class...> class Operation, typename... Arguments> 
    constexpr bool is_detected_v = detail::is_detected<void_t<>, Operation, Arguments...>::value; 
} 

,我們可以很容易地檢查,如果一個類foo包含一個成員函數bar

struct foo { 
    int const& bar(int&&) { return 0; } 
}; 

template<class T> 
using bar_t = decltype(std::declval<T>().bar(0)); 

int main() 
{ 
    static_assert(type_traits::is_detected_v<bar_t, foo>, "not detected"); 
    return 0; 
} 

然而,正如你可以看到,我們無法檢測foo::bar參數類型是int&&。檢測成功,原因0可以傳遞給foo::bar。我知道有很多選項可以檢查(成員)函數的確切簽名。但我想知道,如果可以修改此檢測工具包以檢測foo::bar的參數類型恰好是int&&

[我創建這個例子中的一個live demo]

+0

如果唯一的未知部分是返回類型,這很簡單。你是否也想覆蓋多個參數,你只需要精確地指定一些參數?那成員函數的cv-和ref-qualifiers怎麼樣? – dyp

+2

這樣的事情? http://coliru.stacked-crooked.com/a/38ffdc13080301c6 – dyp

+0

@dyp目前,'is_detected_v '會檢測'T'是否有任何*成員函數'bar',它接受'int'。在第一步中,我想添加一些'is_detected_exact'來檢測'T'是否有一個成員函數'bar',它的參數類型*完全是*'int'或*完全*'int &&'或*完全* 'int const&'等等。在第二步中,我想驗證一個確切的返回類型,但我想這很容易,因爲'bar_t'就是返回類型(只要decltype(...)中的表達式... )'是格式良好的)。 – 0xbadf00d

回答

1

適應的dypJarod42的想法,我ve想出了

template<class T, typename... Arguments> 
using bar_t = std::conditional_t< 
    true, 
    decltype(std::declval<T>().bar(std::declval<Arguments>()...)), 
    std::integral_constant< 
     decltype(std::declval<T>().bar(std::declval<Arguments>()...)) (T::*)(Arguments...), 
     &T::bar 
    > 
>; 

請注意,bar_t將是bar呼叫的返回類型。通過這種方式,我們與工具包保持一致。我們可以通過

static_assert(type_traits::is_detected_v<bar_t, foo, int&&>, "not detected"); 

但是檢測的存在,而這種解決方案不正是我意,我恨,我需要寫「這麼多複雜的代碼」因爲我要檢測每個方法。我問過一個new question針對這個問題。

4

不改變你的type_traits,你可以做

template<typename T, T> struct helper {}; 

template<class T> 
using bar_t = decltype(helper<const int& (T::*)(int&&), &T::bar>{}); 

Demo

+3

哪裏可以用'integral_constant'替換'helper'? – dyp

相關問題