2017-07-12 22 views
1

"has_member"のようなものを作ろうとしています。 Clang(msvc用)を使用するとうまくいく(0,1を得る)が、MSVCを使用しても(1、1が得られる)。MSVC SFINAE:置換が失敗しない

はここ

template<typename T> 
using void_t = void; 

namespace detail { 
    template<typename AlwaysVoid, template<typename...> typename Operator, typename ...Args> 
    struct _is_valid : std::false_type {}; 


    template<template<typename...> typename Operator, typename ...Args> 
    struct _is_valid<void_t<Operator<Args...>>, Operator, Args...> : std::true_type { using type = Operator<Args...>; }; 
} 

template<template<typename ...> typename Operator, typename ...Args> 
using is_valid = detail::_is_valid<void, Operator, Args...>; 

template<typename T> 
using _has_push_back = decltype(std::declval<T>().push_back(std::declval<typename T::value_type>())); 

template<typename T> 
using has_push_back = is_valid<_has_push_back, T>; 

int main() { 
    std::cout << has_push_back<float>::value << " " << has_push_back<std::vector<float>>::value << std::endl; 

    getchar(); 
    return 0; 
} 

IMHO、Operator<Args...>detail::_is_validで失敗しない私のコードです。しかし、私はそれをMSVCのために有効にする方法を理解していません。

私はVisual Studioを使用しています。2017

答えて

3

あなたは試してみてください:

template<typename T> struct make_void { 
    using type = void; 
}; 

template<typename T> 
using void_t = typename make_void<T>::type; 

is_detectedの情報も役立つかもしれません。

+0

このvoid_tは機能します。しかし、私はなぜこの実装が他のものより優れているのか理解していません(これは私の単純なケースで今まで働いていました)。この新しいvoid_tは、彼が "T"の使用を "保証"しているので、より良いでしょうか? –

+0

':: type'はSFINAEを強制し、標準で' void_t'の単純なエイリアスをサポートする変更/欠陥がありました。 – Jarod42

2

Visual StudioはSFINAEでひどいです。彼らが状況を改善したと主張しているにもかかわらず、ClangとGCCが同じコードをうまく処理しても、私が書いたすべてのSFINAEコードではないにもかかわらず(それほど多くはありませんが)動作しないかコンパイルされません。

Microsoftに問題のあるコードをすべて送信すると、修正される可能性が高くなります。

関連する問題