模板中的返回类型未知
Unknown return type in template
我有一个函数
template <typename T1, typename T2>
/*return type*/ foo(MyClass<T1>& bar1, MyClass<T2>& bar2)
{
if (something)
return bar1;
else
return bar2;
}
问题是,我不知道这个函数会返回什么:它可以是MyClass<T1>
的,也可以是MyClass<T2>
的。
我怎样才能让它工作?
T1 和 T2 是 3 个整数的结构,在编译时已知。返回类型取决于这 2 个中较小的一个:例如,对于T1 = <5, 1, 1>
T2 = <4, 4, 7>
返回类型应MyClass<T2>
。
用法示例:
MyClass<5, 2, 8> m1;
MyClass<4, 2, 1> m2;
cout << foo(m1, m2); //should print m2 (I have a method used for that)
你在那里试图实现的目标不能按原样完成。该语言不允许你有一个基于某些运行时数据更改其返回类型的函数。根据您尝试解决的问题,可能会有不同的替代方法,例如确定可用于表示bar1
或bar2
的通用类型,或者重新组织代码,以便根本不需要返回。
也就是说,如果在编译时无法确定something
...如果可以确定,则可以进行一些元编程来确定返回类型是否为所需的返回类型。
你应该提供对真正问题的更高层次的描述,之后你可能会得到更好的想法,知道要采取什么方向。
您可以尝试以下几行:
template <bool value> struct Bool {};
template <typename T, typename U>
T f_impl(T t, U u, Bool<true>) { return t; }
template <typename T, typename U>
T f_impl(T t, U u, Bool<false>) { return u; }
template <int A, int B, int C, int D, int E, int F>
auto f(MyClass<A,B,C> a, MyClass<D,E,F> b)
-> f_impl(a, b, Bool<!(A < D
|| (A == D && B < E)
|| (A == D && B == E && C < F))>())
{
return f_impl(a, b, Bool<!(A < D
|| (A == D && B < E)
|| (A == D && B == E && C < F))>());
}
您可以定义两个函数,对于给定类型,只有一个函数将被实例化:
template <typename T1, typename T2>
struct ChooseFirst;
template <int A1, int B1, int C1, int A2, int B2, int C2>
struct ChooseFirst<MyClass<A1, B1, C1>, MyClass<A2, B2, C2>> {
// this requires constexpr make_tuple (C++14)
static const bool value = std::make_tuple(A1, B1, C1) < std::make_tuple(A2, B2, C2);
// if in your implementation make_tuple is not constexpr, you can write the comparison manually:
// static const bool value = A1 < A2 || (A1 == A2 && (B1 < B2 || (B1 == B2 && C1 < C2)));
};
template <typename T1, typename T2>
typename std::enable_if<ChooseFirst<T1, T2>::value, T1&>::type foo(T1& bar1, T2&) {
return bar1;
}
template <typename T1, typename T2>
typename std::enable_if<!ChooseFirst<T1, T2>::value, T2&>::type foo(T1&, T2& bar2) {
return bar2;
}
演示
我建议做一个回调而不是返回值,记住告诉不要问原则:
template<typename T>
struct op{
void operator ()(T t){}
};
template<>
struct op<int>{
void operator ()(int a){}
};
template<typename T>
struct Func : public op<T>{
int a;
};
template<typename T, typename T2>
void foo( Func<T> t, Func<T2> t2){
t.a = 3;
t2.a = 4;
if( t.a > t2.a ){
t( 3 );
}else{
t2( 5 );
}
}
也许有更好的解决方案。或者你可以在 MyClass 中使用运算符 (),只需对其进行专用化即可。
返回一个union
类型,该类型可以是T1
,也可以是T2
。
由于返回类型必须固定为编译时,因此必须返回可以MyClass<T1>
或MyClass<T2>
的内容。这可以是一个通用对象,例如 boost::any
(在这种情况下有点矫枉过正),也可以是一个公共基础,一个引用(或指针),然后返回。这要求你的类被定义为
class MyClassBase { /* ... */ };
template<typename T>
class MyClass : MyClassBase { /* ... */ };
template<typename T1, typename T2>
MyClassBase& foo(MyClass<T1>&bar1,MyClass<T2>&bar2)
{
if (something)
return bar1;
else
return bar2;
}
您实际上可以使用 RTTI,以便基本MyClassBase
可以告诉它实际上是什么。事实上,这大致就是boost::any
的工作方式。
当然,正如David所说,如果在编译时知道something
,那么你的代码就不是一个好的设计,你应该使用不同的设计,使用编译时解决方案(通过模板元编程技术)。
bar1 和 bar2 都是引用,因此如果您在函数中以某种方式更改它们,它们都会返回。您可以使用返回值来指示哪些:
enum ReturnType
{
BAR1,
BAR2
}
ReturnType foo(MyClass<T1>& bar1, MyClass<T2>& bar2)
{
if (something)
return BAR1;
else
return BAR2;
}
int main()
{
MyClass<T1> t1;
MyClass<T2> t2;
ReturnType ret = foo(t1, t2);
if(ret == BAR1)
{
// do what you want in case of MyClass<T1>
}
else if(ret == BAR2)
{
// do what you want in case of MyClass<T2>
}
}
另一种可能更接近您想要的方法是使用基类指针:
class Base
{
}
template<typename T>
class MyClass : public Base
{
// ...
}
Base* foo(MyClass<T1>& bar1, MyClass<T2>& bar2)
{
if (something)
return &bar1;
else
return &bar2;
}
正如 vsoftco 在评论和 Walters 回答中提到的,如果这是您的偏好,返回参考也可以。
Base& foo(MyClass<T1>& bar1, MyClass<T2>& bar2)
{
if (something)
return bar1;
else
return bar2;
}
- 如何获取std::result_of函数的返回类型
- 奇怪的结构&GCC&clang(void*返回类型)
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 为什么与常规GCC不同,即使有"学究性错误",MinGW-GCC也能容忍丢失的返回类型
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 函数作为模板参数,是否对返回类型强制约束
- C++中函数的向量返回类型引发错误
- 检查函数返回类型是否与STL容器类型值相同
- 为什么返回类型中需要typename?C++
- QtQuick - qml:28:错误:未知方法返回类型:自定义类型
- qml 未知方法返回类型:ArchiveFile*,即使调用了 qmlRegisterUncreatableType
- 模板函数的返回类型未知,使用 decltype 时代码重复
- 从未知dll(c++)中检索函数(名称、返回类型、参数)
- 是否可以声明指向未知(编译时)返回类型的函数的指针
- 函数返回类型和名称之间存在未知关键字
- 模板中的返回类型未知
- C++中具有多态模板类的未知方法返回类型
- 模板类的返回类型未知
- 对链表c++中的未知返回类型使用void指针