C++ 不能';t推导模板参数
我正在尝试使用与以下类似的API:C++ 不能';t推导模板参数,c++,templates,boost-optional,C++,Templates,Boost Optional,我正在尝试使用与以下类似的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
#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;
}
};
您有针对此类场景的解决方案吗?(我不能接触API)编译器的错误非常清楚:因为t不依赖于任何函数参数,并且您没有显式地传递该t,所以编译器无法推断t的值 请注意,这些a和b选项具有不同的类型,因此get()函数尝试返回多个不同的类型(因此您尝试使用模板化的可选选项?)
C++不能以这种方式工作,因为类型应该在编译时确定,而您的决定取决于运行时值(开关)。考虑返回一个变量类型,如Booo::Apple。
AS @ MUMA33626已经指出,您的<代码> GET()/Case>函数具有不同的返回类型。但是既然
A
和B
具有公共基类base
,为什么不使用返回类型base&
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;
}
当然,只有在API保证get_A()
或get_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;
}
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;
}
boost::可选获取(M&M)
{
boost::可选基;
开关(m型)
{
案例M::t_A:
base=m.get_A();
打破
案例M::t_B:
base=m.get_B();
打破
违约:
投掷;
};
返回基地;
}
只是为了确定这个bug:这是导致boost::optional不尊重继承的bug吗?@rahman这个bug阻止您将boost::optional
转换为Base&
。但是它不影响第二个例子,所以你可以用它。现在我很困惑!您的第二个示例在我的boost版本中编译得很好,但我不明白为什么?“初始化一个本地boost::optional base
并返回它”和“直接返回m.get_a()
”之间有什么区别?它们都是转换
,不是吗?@rahman我真的不知道,只看到get_3()
编译失败,你可以问一个新问题
#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
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;
}