我的示例代码下面的代码片段: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