2017-08-16 4 views
0

テンプレートの型名としてフレンドリーな名前を付けようとしています。関数内のいくつかの場所で名前を使用する必要があるからです。以下に示すようにタイプは、パラメータパック内の他のテンプレート引数の数に基づいて推測されている:テンプレートタイプ!= Deduced type

#include <cassert> 
#include <functional> 
#include <type_traits> 

template < typename ... TArgs, typename Functor = std::function< std::conditional_t< sizeof...(TArgs) == 0, int(), int (TArgs...) > > > 
void DoStuff(const Functor & func, TArgs ... args) { 
    if constexpr (sizeof...(TArgs) == 0) 
     assert(typeid(Functor).hash_code() == typeid(std::function<int()>).hash_code()); 
    else 
     assert(typeid(Functor).hash_code() == typeid(std::function<int (TArgs...)>).hash_code()); 
} 

int main(int argc, char * argv[]) { 
    DoStuff([]() { return 5; }); 
    DoStuff([] (int a) { return a; }); 

    return 0; 
} 

これはうまくコンパイルが、別名Functorが実際にstd::function<>ではないので、両方のアサーションは失敗します。一方、私は以下のように、それは完璧に動作typeid呼び出しでFunctorの定義を繰り返すようにコードを変更した場合:

#include <cassert> 
#include <functional> 
#include <type_traits> 

template < typename ... TArgs, typename Functor = std::function< std::conditional_t< sizeof...(TArgs) == 0, int(), int (TArgs...) > > > 
void DoStuff(const Functor & func, TArgs ... args) { 
    if constexpr (sizeof...(TArgs) == 0) 
     assert(typeid(std::function< std::conditional_t< sizeof...(TArgs) == 0, int(), int (TArgs...) > >).hash_code() == typeid(std::function<int()>).hash_code()); 
    else 
     assert(typeid(std::function< std::conditional_t< sizeof...(TArgs) == 0, int(), int (TArgs...) > >).hash_code() == typeid(std::function<int (TArgs...)>).hash_code()); 
} 

int main(int argc, char * argv[]) { 
    DoStuff([]() { return 5; }); 
    DoStuff([] (int a) { return a; }); 

    return 0; 
} 

なぜ(typname Functor = ...を使用して)最初の宣言間違っては何ですか?そのエイリアスを作る別の方法はありますか? 2番目の質問に答えるには、解がconst式であれば問題ありませんが、例はtypeidのためにconstexprではないことに注意してください。

+0

@ Jarod42これは両方のアサーションにはまだ失敗します:/ – Howard

+1

解決しようとしている実際の問題は何ですか?なぜこのエイリアスが必要だと思いますか? – Barry

+0

@Barry私は必要な3つの場所で定義を繰り返す必要をなくしたいと思います。私はむしろ定義を一度行い、どこでもエイリアスを使用したいと考えています。 – Howard

答えて

1

最初の宣言(typename Functor = ...を使用)が間違っているのはなぜですか?

テンプレートパラメータFunctorのデフォルトのタイプを指定しています。しかし、デフォルトの型は、型が指定されていないか、または推測されていない場合にのみ使用されます。この場合、テンプレートの控除では、どちらの場合もラムダの固有の型が呼び出されたもの(Args...は空のパックとみなされます)が何であっても、どちらの場合でもFunctorが推測されます。

これは、デフォルトの関数引数が提供されていない場合と同様です。

あなたのassert()が達成するはずのものはわかりませんが、タイプを確認する場合はstatic_assertを使用してください。

+0

ああ、それは今や理にかなっています。私はそれがデフォルトのテンプレートパラメータを推測しようとしているのか分からなかった。私は間違った前提のもとで、それが指定されたときにはデフォルトではなかっただけです。アサーションは、それが私が意図したことをしなかったことを示すコードだけであり、それが私が期待していたものについてのいくつかの光を放つ。上記のコードを 'std :: function <>'型の名前を別名に変更することはできますか? – Howard

+0

@Howardあなたは 'using T = int;'のような意味ですか? – Barry

+0

は 'using'ステートメントとまったく同じです。作成されたエイリアスのみがスコープされ、パラメータタイプに名前を付けるために使用できるように、私はドキュメントから完全に理解していません。 – Howard

関連する問題