2

次のコードのほとんどは、Piotr Skotnickiによってanswerから取得されています。ラムダオブジェクトはによって生成されたので、型パラメータ名を変更すると、テンプレートの置換が失敗する - コンパイラのバグ?

#include <iostream> 

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

template <typename...> 
using void_t = void; 

template <typename F> 
struct call_operator; 

template <typename C, typename R, typename... A> 
struct call_operator<R(C::*)(A...)> : identity<R(A...)> {}; 

template <typename C, typename R, typename... A> 
struct call_operator<R(C::*)(A...) const> : identity<R(A...)> {}; 

template <typename F> 
using call_operator_t = typename call_operator<F>::type; 

template <typename, typename = void_t<>> 
struct is_convertible_to_function 
    : std::false_type {}; 

template <typename L> 
struct is_convertible_to_function<L, void_t<decltype(&L::operator())>> 
    : std::is_assignable<call_operator_t<decltype(&L::operator())>*&, L> {}; 

template <typename, typename = void_t<>> 
struct is_callable_object 
    : std::false_type {}; 

template <typename L> 
struct is_callable_object<L, void_t<decltype(&L::operator())>> 
    : std::true_type {}; 


int main() 
{ 
    auto x = []() {}; 
    std::cout << std::boolalpha << is_callable_object<decltype(x)>::value; 
    std::getchar(); 
} 

これは予想通りtrueを、印刷します。私はそれを試して、私は3

は、次のコードを考えてみましょうMSVC 14.0アップデートのバグであると信じるものを発見されましたコンパイラはoperator()を実装しています。

のは、今(私が見たものから、is_convertible_to_function原因この問題で使用されるタイプ名とは異なるもの)TLからis_callable_objectに型パラメータ名を変更してみましょう。

template <typename, typename = void_t<>> 
struct is_callable_object 
    : std::false_type {}; 

template <typename T> 
struct is_callable_object<T, void_t<decltype(&T::operator())>> 
    : std::true_type {}; 

突然、これはfalseを印刷します。 is_callable_objectはそれに依存しないので、is_convertible_to_funtionは問題にならないはずです。実際、もし私がis_convertible_to_functionを取り除くと、この問題は消えてしまいます。私が望む任意のタイプ名を使うことができます。

私が言ったように、私はバグだと思うので、これはC++標準では奇妙な動作ではないことを確認するためにこの質問をしています。これに対する回避策は非常に簡単です。

答えて

2

式sfinaeはmsvc 2015で機能しません。動作するすべてのケースは偶然であり、信頼できません。 decltypeは、msvc 2015のsfinaeを確実ににするために使用することはできません。

停止し、別の解決策を見つける。たぶんコンパイラ組み込み関数を試してみてください。

パラメータ名が一致したときにうまく動作しないと仮定しないでください。それ以外の方法でうまく動作しない場合や、わずかに異なるプログラムで動作する場合があります。

回避策は信頼できません。

+0

あなたの声明があまりにも極端ではないかと疑問に思っていましたが、マイクロソフト自身でさえそれが認められます:https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for- expression-sfinae-in-vs-2015-update-1 /。ああ、私は実験を続けていきます、ありがとう。 – szczurcio

関連する問題