2017-12-19 20 views
3

は、次のコードを考えてみましょう:void_tとvariadicテンプレートを混在していますか?

template <class F, class... Args, class = std::void_t<>> 
struct is_invokable 
: std::false_type {}; 
template <class F, class... Args> 
struct is_invokable<F, Args..., std::void_t<std::invoke_result_t<F, Args...>>> 
: std::true_type {}; 

目標は、タイプFの呼び出し可能なタイプArgs...の引数を持つ呼び出し可能であるかどうかを指示することである形質を持つことです。

しかし、それはコンパイルに失敗:C++ 17でこれを行うには(エレガント)の方法は何

error: parameter pack 'Args' must be at the end of the template parameter list 

+4

まあ、ようArgs...

何かをラップするヘルパーstructis_invokable_h)とstd::tupleの使用を提案します?そこにそれを置きます。 – Barry

+0

Huh。私はそのタイプがパックを最終的な位置に置くことを必要としていることに気付かなかった。関数は、デフォルトの引数を与えるか、またはそれらを推論することはできません。 –

答えて

6
namespace details { 
    template <class F, class, class... Args> 
    struct is_invokable : std::false_type {}; 
    template <class F, class... Args> 
    struct is_invokable<F, std::void_t<std::invoke_result_t<F, Args...>>, Args...> 
    : std::true_type {}; 
} 
template <class F, class... Args> 
using is_invokable=typename ::details::is_invokable<F, void, Args...>::type; 
1

は、私はあなたが `void`を置くことができる他、他の端部よりも

#include <type_traits> 
#include <utility> 

template <typename, typename, typename = void> 
struct is_invokable_h : std::false_type 
{}; 

template <typename F, typename ... Args> 
struct is_invokable_h<F, std::tuple<Args...>, 
         std::void_t<std::invoke_result_t<F, Args...>>> 
    : std::true_type 
{}; 

template <typename F, typename ... Args> 
struct is_invokable : is_invokable_h<F, std::tuple<Args...>> 
{}; 

int foo (int) 
{ return 0; } 

int main() 
{ 
    static_assert(true == is_invokable<decltype(foo), int>{}); 
    static_assert(false == is_invokable<decltype(foo), int, int>{}); 
} 
+2

またはC++で導入された[std :: is_invocable](http://en.cppreference.com/w/cpp/types/is_invocable)17。 –

+0

あなたは正しいですか: 'std :: is_invocable'。しかし、テンプレートのバリデーションリストの後で、デフォルトのテンプレートタイプの問題を回避する方法を私の意図で示しました。 – max66

関連する問題