2015-11-15 57 views
2

我有以下功能:如何專門化一個元組參數的函數?

template <typename Functor, typename Arg> 
decltype(auto) call(Functor f, Arg &&arg) { // (1) 
    // .. 
} 

我想創建的情況下,專業化,當argtuple。我想:

template <typename Functor, typename... Args> 
decltype(auto) call(Functor f, std::tuple<Args...> &&args) { // (2) 
    // .. 
} 

自身的其中一期工程,但是當兩者都存在,(1)原來是即使參數是一個元組更好的匹配。我正在使用clang 3.7來編譯代碼。

+1

後者不是一個特例,而是一種超負荷採取一個元組右值,你傳遞一個右值? –

+0

@PiotrSkotnicki在某些情況下,我想。 (1)比(2)更好,如果(2)不工作(1) –

回答

2

,如果你想從寫醜SFINAE騰出自己你需要做一個間接層。相反,標籤調度的,你也可以委託給一個類模板,但我更喜歡標籤

template<typename> class type { }; 

template <typename Functor, typename Arg> 
decltype(auto) call(Functor f, Arg &&arg) { 
    return call(f, std::forward<Arg>(arg), type<std::decay_t<Arg>>()); 
} 

template <typename Functor, typename Arg, typename T> 
decltype(auto) call(Functor f, Arg &&arg, type<T>) { 
    ... 
} 

template <typename Functor, typename Arg, typename ...T> 
decltype(auto) call(Functor f, Arg &&arg, type<std::tuple<T...>>) { 
    ... 
} 
+0

不錯,很清楚。在實際使用中,將'type'和helper'call's放在'impl'命名空間中可能會很好。 –

+1

@JohanLundberg你是對的。但是你需要注意調用函數的順序,因爲'type'不再是查找'call'的其他重載的ADL提示。編輯:如果你把調用放到相同的命名空間,這將工作,nvm :) –

1

我發現你的例子沒有工作(和vs2015同意)

http://ideone.com/dNTsrf

基本情況是一個通用的引用,它需要rvalue和rvalues(和引用)。 (現場演示http://ideone.com/kCBv3d

decltype(auto) call(int &&arg) { // (1) 
    std::cout << "Base case" << std::endl; 
}  
decltype(auto) call(std::tuple<int> &&args) { 
    std::cout << "TTT" << std::endl; 
} 
/// main: 
call(std::tuple<int>{1}); // TTT 
call(2);     // Base case 
std::tuple<int> ti{5};  
call(1,ti);    // Base case (as expected!) 
call(1,std::move(ti)); // TTT 

注意,你的重載採用R值引用(不轉發引用),所以任何東西(左值引用)將使用基本情況。

據我瞭解,這都是超載的,但相關的讀取是這個職位由Herb薩特:http://www.gotw.ca/publications/mill17.htm

+0

不是(1)如果其他超載更專業化並且同樣可行 –

+0

那麼問題恰好與案例叫(1,ti)';我沒有使用std :: move的自由,因爲它是從泛型代碼調用的。 –

+0

@TamásSzelei,請注意,這意味着你實際上沒有得到這種情況下的移動語義。如果你想這樣做,你應該修改(如果可能)泛型代碼來使用'std :: forward <>'。這正是這個案例。 –

相關問題