我的示例代碼下面的代碼片段:C++:模板參數推導通過模板函數作爲參數傳遞給其他模板函數時
的想法是,有一個容器類,這裏所謂的Box
,那我們可能要通過mapping函數對當前內容創建此容器的新版本。
#include <iostream>
#include <tuple>
template <typename TContent>
class Box
{
TContent d_content;
public:
Box(TContent content)
:
d_content(content)
{}
TContent content() const
{
return d_content;
}
template <typename Function>
auto transform(Function fun) -> decltype(Box{fun(d_content)})
{
return Box{fun(d_content)};
};
};
template <typename TElem>
std::tuple<TElem, TElem> toTuple(TElem thing)
{
std::cout << "Transforming " << thing << "to tuple.\n";
return std::make_tuple(thing, thing);
}
int main() {
std::cout << "Hello World!\n";
Box<int> mybox{10};
Box<int> box2 = mybox.transform([](int content){ return content * 2;});
std::cout << "Transformed box: " << box2.content() << '\n';
Box<std::tuple<int, int>> box3 = mybox.transform(&toTuple); // <- Template argument deduction/substitution fails here!
std::cout << "Transformed box: " << std::get<0>(box3.content()) << '\n';
}
在管線42,在其中創建BOX3,模板參數推導/置換失敗:
main.cpp: In function 'int main()':
main.cpp:42:60: error: no matching function for call to 'Box<int>::transform(<unresolved overloaded function type>)'
Box<std::tuple<int, int>> box3 = mybox.transform(&toTuple);
^
main.cpp:22:8: note: candidate: template<class Function> decltype (Box<TContent>{fun(((Box<TContent>*)this)->Box<TContent>::d_content)}) Box<TContent>::transform(Function) [with Function = Function; TContent = int]
auto transform(Function fun) -> decltype(Box{fun(d_content)})
^~~~~~~~~
main.cpp:22:8: note: template argument deduction/substitution failed:
main.cpp:42:60: note: couldn't deduce template parameter 'Function'
Box<std::tuple<int, int>> box3 = mybox.transform(&toTuple);
^
exit status 1
這似乎是試圖通過一個模板函數時的情況下(函數模板?)到一個本身需要模板參數參數的函數。
迄今爲止發現的避免這種情況的唯一方法是將所有模板函數包裝在lambdas或其他非模板函數中。這當然不是最理想的,因爲它引入了大量的樣板。
爲什麼模板參數推導失敗在這種情況下,是有沒有辦法改變Box
類的代碼(和/或它的transform
成員函數),以確保模板參數推導確實工作?
(給出的代碼是C++ 11作爲repl.it尚不支持C++ 14。在C++ 14的主要區別將是的transform
尾隨返回類型可以被省略。該錯誤,但是,仍然是相同的,我很高興與解決方案(只)工作在C++ 14爲好)
謝謝。出於某種原因,C++ 11和C++ 14愉快地編譯格式錯誤的decltype。無論如何,將它改爲「Box」會使它正確,對嗎? –
Qqwy
至於''toTuple'是一個函數模板,不是函數,你不能將它傳遞給另一個函數模板,因爲它沒有類型,所以不能推導出來。「 - >是否有將函數模板傳遞給另一個函數模板的情況,可以推導出它? – Qqwy
@Qqwy是的,你可以。不,沒有。 – Barry