为什么是C++;模板类型匹配与基类引用不匹配,如何使其与基类引用匹配? 这是我的C++程序代码< /p> #include <iostream> #include <memory> using namespace std; template <typename T> struct A { T x; }; template <typename T> struct B:A<T> { }; template <typename T> void func(const A<T>& t) { cout<<"2"<<endl; } template <typename T> void func(const T& t) { cout<<"1"<<endl; } int main() { B<int> b; func(b); } #包括 #包括 使用名称空间std; 模板 结构A{tx;}; 模板 结构B:A{}; 模板 无效函数(常数A&t){ 库特解1
您可以使用为什么是C++;模板类型匹配与基类引用不匹配,如何使其与基类引用匹配? 这是我的C++程序代码< /p> #include <iostream> #include <memory> using namespace std; template <typename T> struct A { T x; }; template <typename T> struct B:A<T> { }; template <typename T> void func(const A<T>& t) { cout<<"2"<<endl; } template <typename T> void func(const T& t) { cout<<"1"<<endl; } int main() { B<int> b; func(b); } #包括 #包括 使用名称空间std; 模板 结构A{tx;}; 模板 结构B:A{}; 模板 无效函数(常数A&t){ 库特解1,c++,templates,matching,C++,Templates,Matching,您可以使用std::enable_if和模板化模板参数来更好地匹配函数,如: #include <iostream> #include <memory> #include <type_traits> using namespace std; template <typename T> struct A { T x; }; template <typename T> struct B:A<T> { }; templa
std::enable_if
和模板化模板参数来更好地匹配函数,如:
#include <iostream>
#include <memory>
#include <type_traits>
using namespace std;
template <typename T>
struct A { T x; };
template <typename T>
struct B:A<T> { };
template <template <typename...> typename T, typename ...Args, typename = std::enable_if_t<std::is_base_of_v<A<Args...>, T<Args...>>>>
void func(const T<Args...>& t) {
cout<<"2"<<endl;
}
template <typename T>
void func(const T& t) {
cout<<"1"<<endl;
}
int main() {
B<int> b;
func(b);
func(5);
}
这再也不行了
解决方案2
基于,您可以创建更通用的类型特征。与解决方案1一样,此解决方案对其模板参数没有限制
namespace detail
{
template <template <typename...> typename Base>
struct template_base_detector
{
template <typename... Args>
constexpr std::true_type operator()(Base<Args...>*);
constexpr std::false_type operator()(...);
};
}
template <template <typename...> typename Base, typename T>
struct is_template_base_of
: decltype(std::declval<detail::template_base_detector<Base>>()((T*)nullptr)) {};
// since C++ 14
template <template <typename...> typename Base, typename T>
constexpr bool is_template_base_of_v = is_template_base_of<Base, T>::value;
C++ 11和14
我们必须退回到标签发送:
namespace detail
{
template <typename T>
void func(std::true_type, const T& t)
{
std::cout << 2 << endl;
}
template <typename T>
void func(std::false_type, const T& t)
{
std::cout << 1 << endl;
}
}
template <typename T>
void func(const T& t)
{
detail::func(is_template_base_of<A, T>{}, t);
}
namespace details{
template <typename T>
void func(std::true_type,const A<T>& t) {
std::cout<<"2"<<std::endl;
}
template <class T>
void func(std::false_type,const T& t) {
std::cout<<"1"<<std::endl;
}
}
template <typename T>
void func(const T& t) {
details::func(has_template_base<A,T>,t);
}
名称空间详细信息
{
模板
无效函数(标准::真值类型,常数T&T)
{
std::cout标签调度
首先,我们编写一个trait来检测是否有模板作为基础:
namespace details {
template<template<class...>class Z>
struct htb {
template<class...Ts>
constexpr std::true_type operator()(Z<Ts...>*){return {};}
constexpr std::false_type operator()(...){return {};}
};
}
template<template<class...>class Z, class X>
constexpr inline auto has_template_base = details::htb<Z>{}((X*)nullptr);
名称空间详细信息{
模板
结构htb{
模板
constexpr std::true_类型运算符()(Z*){return{};}
constexpr std::false_类型运算符()(…){return{};}
};
}
模板
constexpr inline auto具有_template_base=details::htb{}((X*)nullptr);
现在,我们可以使用新特性标记dispatch:
namespace detail
{
template <typename T>
void func(std::true_type, const T& t)
{
std::cout << 2 << endl;
}
template <typename T>
void func(std::false_type, const T& t)
{
std::cout << 1 << endl;
}
}
template <typename T>
void func(const T& t)
{
detail::func(is_template_base_of<A, T>{}, t);
}
namespace details{
template <typename T>
void func(std::true_type,const A<T>& t) {
std::cout<<"2"<<std::endl;
}
template <class T>
void func(std::false_type,const T& t) {
std::cout<<"1"<<std::endl;
}
}
template <typename T>
void func(const T& t) {
details::func(has_template_base<A,T>,t);
}
名称空间详细信息{
模板
无效函数(标准::真实类型,常数A&t){
std::coutForvoid func(const T&T)
,T
被推断为B
void func(const B&T)
比void func(const a&T)
更匹配。我应该如何更改它以使其匹配void func(const a&T)
?您可以为每个派生类编写代理重载,例如模板void func(const B&t){func(static_cast(t));}
。这听起来合理吗?所有派生类是否都遵循相同的模式:模板结构派生:A
?谢谢,您的建议在这种情况下很有帮助。A
有许多子类。在我的程序中,有许多类似于模板void func2(const A&p1,const A&p2)的地方
。如果我使用代理重载,由于笛卡尔积,许多代理重载都必须编写。奇怪的是,当添加另一层()时,特定于问题的解决方案不起作用。但是,这些特性……我理解类型特性是如何工作的,但是编译器如何在操作符()中推断出Ts…
?只需查看X
(从has_template_base
)的类型层次结构,@Timo-template-argument推导就可以对一个类型及其基类型应用?最终,它将a*
对a*
进行测试,并将{Ts..
推断为{int}
@StoryTeller这种含糊不清的说法有点让人痛苦。我发誓我已经让它起作用了,但我现在遇到了问题。我正在否定这种解决方案。