无法推断模板参数
couldn't deduce template parameter
本文关键字:参数 更新时间:2023-10-16
我正在尝试使用类似于以下的API:
#include<iostream>
#include<boost/optional.hpp>
class Base
{
int id;
public:
int get_id()
{
return id;
}
};
class A : public Base
{
};
class B : public Base
{
};
class M
{
public:
enum Type
{
t_A,
t_B
};
Type type;
boost::optional<A&> a;
boost::optional<B&> b;
boost::optional<A&> get_A()
{
return a;
}
boost::optional<B&> get_B()
{
return b;
}
};
我需要通过任何派生类到达基类。所以我创建了一个像这样的模板化函数:
template<class T>
boost::optional<T&> get(M & m)
{
switch(m.type)
{
case M::t_A :
return m.get_A();
case M::t_B :
return m.get_B();
default:
throw;
};
}
int main()
{
M m;
//... initialization of m
int i = get<>(m)->get_id();
return 0;
}
但是我的函数的模板参数不能被推导出来:
template_sp_1.cpp:63:17: error: no matching function for call to ‘get(M&)’
int i = get<>(m)->get_id();
^
template_sp_1.cpp:63:17: note: candidate is:
template_sp_1.cpp:46:21: note: template<class T> boost::optional<T&> get(M&)
boost::optional<T&> get(M & m)
^
template_sp_1.cpp:46:21: note: template argument deduction/substitution failed:
template_sp_1.cpp:63:17: note: couldn't deduce template parameter ‘T’
int i = get<>(m)->get_id();
尝试以下任何操作都是不可能的;显然是因为使用了boost::optional
:
int i = get<Base>(m)->get_id();
int i = get<A>(m)->get_id();
int i = get<B>(m)->get_id();
对于这种情况,你有什么解决方案吗?(我不能触摸API)
编译器错误非常明显:由于T不依赖于任何函数参数,并且您没有显式传递该T,因此编译器无法推断T的值
请注意,这些a和b可选具有不同的类型,因此您的get()函数试图返回多个不同的类型(因此您使用模板化的可选?)
c++不以这种方式工作,因为类型应该在编译时确定,而您的决定取决于运行时值(开关的事情)。考虑返回一个像boost::variant这样的变体类型
正如@Manu343726已经指出的,您的get()
函数具有不同的返回类型。但是既然A
和B
有共同的基类Base
,为什么不使用返回类型Base&
呢?
在boost::optional
中有一个关于引用的bug,在boost 1.58中修复了,所以你至少需要这个版本。我修改了你的例子来展示它是如何工作的:
#include <boost/optional.hpp>
#include <boost/version.hpp>
#include <iostream>
#if BOOST_VERSION < 105800
#error boost version must be at least 1.58
#endif
class Base
{
int id;
public:
Base(int id) : id(id) {}
int get_id()
{
return id;
}
};
class A : public Base
{
public:
A() : Base(100) {}
};
class B : public Base
{
public:
B() : Base(999) {}
};
class M
{
public:
enum Type
{
t_A,
t_B
};
Type type;
boost::optional<A&> a;
boost::optional<B&> b;
boost::optional<A&> get_A()
{
return a;
}
boost::optional<B&> get_B()
{
return b;
}
};
Base& get(M & m)
{
switch(m.type)
{
case M::t_A :
return (*(m.get_A()));
case M::t_B :
return (*(m.get_B()));
default:
throw;
};
}
int main()
{
A a;
M m;
m.type = M::t_A;
m.a = a;
Base& base = get(m);
std::cout << base.get_id() << std::endl;
return 0;
}
这个例子将输出:
100
这当然只在运行时有效,如果API保证get_A()
或get_B()
返回一个包含有效引用的可选值。如果不能保证这一点,您可以使用如下内容:
boost::optional<Base&> get(M & m)
{
boost::optional<Base&> base;
switch(m.type)
{
case M::t_A:
base = m.get_A();
break;
case M::t_B :
base = m.get_B();
break;
default:
throw;
};
return base;
}
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 使用指向成员的指针将成员函数作为参数传递
- 没有名称的C++模板参数
- 如何将enable-if与模板参数和参数包一起使用