2015-11-01 3 views
2
namespace detail { 
template <class F, class... Args> 
inline auto INVOKE(F&& f, Args&&... args) -> 
    decltype(std::forward<F>(f)(std::forward<Args>(args)...)) { 
     return std::forward<F>(f)(std::forward<Args>(args)...); 
} 

template <class Base, class T, class Derived> 
inline auto INVOKE(T Base::*pmd, Derived&& ref) -> 
    decltype(std::forward<Derived>(ref).*pmd) { 
     return std::forward<Derived>(ref).*pmd; 
} 

template <class PMD, class Pointer> 
inline auto INVOKE(PMD pmd, Pointer&& ptr) -> 
    decltype((*std::forward<Pointer>(ptr)).*pmd) { 
     return (*std::forward<Pointer>(ptr)).*pmd; 
} 

template <class Base, class T, class Derived, class... Args> 
inline auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args) -> 
    decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...)) { 
     return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...); 
} 

template <class PMF, class Pointer, class... Args> 
inline auto INVOKE(PMF pmf, Pointer&& ptr, Args&&... args) -> 
    decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...)) { 
     return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...); 
} 
} // namespace detail 

template< class F, class... ArgTypes> 
decltype(auto) invoke(F&& f, ArgTypes&&... args) { 
    return detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...); 
} 

Я видел реализация выше здесь:Как работает std :: invoke (C++ 1z)?

http://en.cppreference.com/w/cpp/utility/functional/invoke

Тогда Интересно, как компиляторы соответствуют точную версию требуемой. Работает ли SFINAE на возвращаемом типе возврата?

+1

Обратите внимание, что эта реализация несколько нарушена, так как она принимает некоторые конструкции, которые являются недействительными в соответствии со стандартом. –

+0

@ T.C. Вы имеете в виду PMF или PMD? – iDingDong

+0

@ T.C. не могли бы вы рассказать об этом? – melak47

ответ

3

ли SFINAE работают на хвостохранилище типа возврата?

Да. Синтаксис возвращаемого типа возврата не включает никаких новых функций, он просто упрощает запись некоторых типов возвращаемых типов, зависящих от типов параметров.

template <class F, class... Args> 
inline auto INVOKE(F&& f, Args&&... args) -> 
    decltype(std::forward<F>(f)(std::forward<Args>(args)...) { ... } 

мог бы то же самое было написано в

template <class F, class... Args> 
inline decltype(std::forward<F>(std::declval<F&>())(std::forward<Args>(std::declval<Args&>())...)) 
INVOKE(F&& f, Args&&... args) { ... } 

, например, и то же самое для всех остальных. Это может быть упрощено, но даже если вы упростите его, тот факт, что тип возврата не может использовать тот же синтаксис, что и выражение return, затрудняет отслеживание происходящего. Отсюда новый синтаксис.

Единственный раз, когда SFINAE не работает, выводится возвращаемый тип. Они также используют auto, но это не ключевое слово auto, которое отключает SFINAE.

+0

Спасибо! BTW Я просто заметил, что мое неудобное правописание от вас цитирует :-( – iDingDong

+0

@iDingDong Не беспокойтесь об этом, он фактически работает как «хвост», так и «trailing». :) – hvd

+0

И я все еще удивляюсь, есть ли какой-либо C++ 1z ключевой язык, необходимый для SFINAE для работы над этим случаем? – iDingDong

Смежные вопросы