【发布时间】:2017-06-18 13:08:53
【问题描述】:
问题
我的代码中有以下方案,
#include <memory>
#include <iostream>
template <class T>
struct A {};
template <class T>
struct Z {};
template <class T, class U>
struct B : A<T>, Z<U> {};
template <class T>
struct C : B<T, T> {};
template <class T>
void foo(const std::shared_ptr<A<T>>& a)
{
std::cout << "HI !" << std::endl;
}
int main()
{
auto c = std::make_shared<C<char>>();
foo(c);
return 0;
}
但编译器无法正确替换模板参数:
main.cpp: In function 'int main()':
main.cpp:26:10: error: no matching function for call to 'foo(std::shared_ptr<C<char> >&)'
foo(c);
^
main.cpp:17:6: note: candidate: template<class T> void foo(const std::shared_ptr<A<T> >&)
void foo(const std::shared_ptr<A<T>>& a)
^~~
main.cpp:17:6: note: template argument deduction/substitution failed:
main.cpp:26:10: note: mismatched types 'A<T>' and 'C<char>'
foo(c);
^
修复
所以我把foo改成了这个:
template <class T, template <class> class U>
void foo(const std::shared_ptr<U<T>>& a)
{
std::cout << "HI !" << std::endl;
}
更好的方法?
它可以工作,但感觉不对,因为类型上的模板约束现在真的很松散,通常最终会导致更加模糊的错误消息。
有没有更好的方法来处理这类模板推演失败?
使用 Coliru 上的示例
【问题讨论】:
-
至于为什么:模板参数扣除时不考虑自定义转换。为
shared_ptr<Base>类型的参数传递shared_ptr<Derived>需要这样的转换。你可以写foo(std::static_pointer_cast<A<char>>(c)); -
@IgorTandetnik 谢谢。这是“设计”吗?您知道为什么不考虑此类转化吗?
-
假设你有
template <typename T> void f(A<T>);并且你用f(seeminglyUnrelated);调用它为了使这个工作,编译器必须尝试每个存在的类型T,希望seeminglyUnrelated可能有一个用户定义的转换为A<T>。或者,尝试所有可能适用于seeminglyUnrelated的用户定义转换序列,希望其中一个(并且只有一个)可能为某些 U 生成类似于A<U>的类型。两者都不可行,并且所以编译器不需要这样做。
标签: c++ templates inheritance c++14 template-argument-deduction