2017-08-16 168 views
0

我試圖給出一個友好的名稱,類型爲模板類型名,因爲我需要在函數內的幾個地方使用的名稱。基於在參數組其他模板參數數量的類型被推斷,如下圖所示:模板類型!=推演型

#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<>。在另一方面,如果我改變代碼重複的Functor定義在typeid調用它完美的作品,象下面這樣:

#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 = ...)不正確的?有沒有不同的方式來製作別名?請注意,在回答第二個問題,這是確定如果解決方案是一個常量表達式,這些例子只是不constexpr使用typeid的感覺。

+0

@ Jarod42還是失敗,都斷言:/ – Howard

+1

什麼是你要解決實際問題?你爲什麼認爲你需要這個別名? – Barry

+0

@Barry我想消除在我需要的3個地方重複定義的需要。我寧願定義一次,並在其他地方使用別名 – Howard

回答

1

爲什麼第一個聲明(使用typename Functor = ...)不正確的?

您正在爲模板參數Functor提供默認類型。但是默認類型僅在類型未另行指定或推導時使用。在這種情況下,模板扣將演繹在這兩種情況下Functor是任何獨特類型的拉姆達的是,它被調用,(而Args...推導出一個空包)。

這類似於默認設置,當他們不被使用的功能參數。

我不確定你的assert()應該完成什麼,但如果你正在檢查類型,你應該使用static_assert

+0

啊,現在有道理。我不知道它會試圖推斷一個默認的模板參數。我是在不正確的假設下,它只是在指定時不是默認的。這些斷言僅在該代碼中才表明它沒有按照我的意圖去做,並且展示了我期望的結果。上面的代碼是否可以重寫爲'std :: function <>'類型的名稱? – Howard

+0

@Howard你的意思是像'使用T = int;'? – Barry

+0

就像'using'語句一樣。我從文檔中完全不瞭解我是否可以使用它,以便創建的別名僅限於該函數的範圍,並且仍然可以用於命名參數類型 – Howard