2017-04-24 32 views
3

我的編譯兩個模板方法失敗,因爲不兼容的CV-預選賽

template <typename T, typename Ret, typename ...Args> 
Ret apply(T* object, Ret(T::*method)(Args...), Args&& ...args) { 
    return (object->*method)(std::forward(args)...); 
}; 

template <typename T, typename Ret, typename ...Args> 
Ret apply(T* object, Ret(T::*method)(Args...) const, Args&& ...args) { 
    return (object->*method)(std::forward(args)...); 
}; 

我的目的是申請會員方法對這些ARGS T類

這是我的測試代碼:

int main() { 
    using map_type = std::map<std::string, int>; 
    map_type map; 
    map.insert(std::make_pair("a", 1)); 
    std::cout << "Map size: " << apply(&map, &map_type::size) << std::endl; //this code work 
    apply(&map, &map_type::insert, std::make_pair("a", 1)); //failed to compile 

    return 0; 
} 

這是編譯器錯誤我ssage:

test.cpp: In function ‘int main()’: 
test.cpp:61:58: error: no matching function for call to ‘apply(map_type*, <unresolved overloaded function type>, std::pair<const char*, int>)’ 
    apply(&map, &map_type::insert, std::make_pair("a", 1)); 
                 ^
test.cpp:11:5: note: candidate: template<class T, class Ret, class ... Args> Ret apply(T*, Ret (T::*)(Args ...), Args&& ...) 
Ret apply(T* object, Ret(T::*method)(Args...), Args&& ...args) { 
    ^~~~~ 
test.cpp:11:5: note: template argument deduction/substitution failed: 
test.cpp:61:58: note: couldn't deduce template parameter ‘Ret’ 
    apply(&map, &map_type::insert, std::make_pair("a", 1)); 
+0

我找到[map :: insert的8個版本](http://en.cppreference.com/w/cpp/container/map/insert)。編譯器應該使用'&map_type :: insert'哪一個? –

回答

6

std::map::insert重載功能。除非你明確地指定了你感興趣的重載 - 編譯器怎麼知道呢?你不能接受它的地址。

解決您的問題,最簡單的方法是讓apply接受任意函數對象和包裝您的來電insert通用拉姆達

template <typename F, typename ...Args> 
decltype(auto) apply(F f, Args&& ...args) { 
    return f(std::forward<Args>(args)...); 
}; 

用法:

::apply([&](auto&&... xs) -> decltype(auto) 
{ 
    return map.insert(std::forward<decltype(xs)>(xs)...); 
}, std::make_pair("a", 1)); 

live wandbox example

額外的語法樣板是不幸的是不可能避免的。這可能會改變未來,請參閱:

  • N3617旨在通過引入「提升」操作來解決這個問題。

  • P0119作者:A. Sutton以不同的方式解決了這個問題,允許超載集合作爲參數傳遞時基本上爲你生成「包裝lambda」。

我不知道如果重載成員函數在上述提案雖然支持。


您也可以通過顯式指定你位數的在發送方過載使用原來的解決方案:

::apply<map_type, std::pair<typename map_type::iterator, bool>, 
     std::pair<const char* const, int>>(
    &map, &map_type::insert<std::pair<const char* const, int>>, 
    std::make_pair("a", 1)); 

正如你可以看到它的不是很漂亮。它可能可以改進一些更好的模板參數扣除,但不是太多。

+0

我需要* f *是我的課程的一個方法,我該如何指定它。 對不起,我的英文不好 –

+1

@PhạmVănThông:你不能傳遞'&std :: map :: insert',因爲你不能接受一個重載函數的地址或者在*函數調用表達式*之外引用它。你可以做的最好的是傳遞一個lambda /函數對象,它將所有內容都轉發給'insert'。您可以捕獲地圖實例或將其作爲一個額外的參數傳遞給lambda。 –

相關問題