[英]couldn't deduce template parameter
I am trying to use an API which is similar to the following: 我正在尝试使用类似于以下内容的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;
}
};
I need to get to the base through any derived class. 我需要通过任何派生类来掌握基础。 So I created a templated function like this:
所以我创建了这样的模板化函数:
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;
}
but my function's template argument cannot be deduced : 但是我的函数的模板参数不能推论:
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();
trying any of the following is not possible; 不能尝试以下任何一种方法; apparently due to using
boost::optional
: 显然是由于使用
boost::optional
:
int i = get<Base>(m)->get_id();
int i = get<A>(m)->get_id();
int i = get<B>(m)->get_id();
Do you have a solution for such scenarios? 您有针对此类情况的解决方案吗? (I can't touch the API)
(我无法触摸API)
The compiler error is pretty clear: Since T does not depend on any function parameter, and you are not passing that T explicitly, the compiler was unable to deduce a value for T. 编译器错误非常明显:由于T不依赖任何函数参数,并且您没有显式传递T,因此编译器无法推断T的值。
Note that those a and b optionals have different types, so your get() function is trying to return multiple different types (Hence your try with a templated optional?) 请注意,那些a和b可选类型具有不同的类型,因此您的get()函数试图返回多个不同的类型(是否尝试使用模板化的可选类型?)
C++ does not work in that way since the type should be determined at compile time, and your decission depends on a runtime value (the switch thing). C ++不能以这种方式工作,因为类型应在编译时确定,而您的决定取决于运行时值(切换对象)。 Consider returning a variant type like boost::variant.
考虑返回像boost :: variant这样的变量类型。
As @Manu343726 already pointed out, your get()
function has varying return types. 正如@ Manu343726已经指出的那样,您的
get()
函数具有不同的返回类型。 But since A
and B
have the common base class Base
, why don't you use a return type of Base&
? 但是,由于
A
和B
具有通用的基类Base
,为什么不使用Base&
的返回类型?
There is a bug in boost::optional
regarding references which was fixed in boost 1.58, so you need at least this version. boost::optional
关于在boost 1.58中已修复的引用存在错误 ,因此至少需要此版本。 I modified your example to show how it could work: 我修改了您的示例以显示其工作方式:
#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;
}
This example will output: 此示例将输出:
100
This of course only works at runtime if the API does guarantee that get_A()
or get_B()
return an optional containing a valid reference. 当然,这仅在API保证
get_A()
或get_B()
返回包含有效引用的可选内容时才在运行时有效。 If this is not guaranteed, you can use something like this: 如果不能保证,可以使用以下方法:
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.