簡體   English   中英

模板中的未知返回類型

[英]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> 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)

你想要實現的目標是不可能的。 該語言不允許您具有基於某些運行時數據更改其返回類型的函數。 根據您嘗試解決的問題,可能有不同的替代方法,例如確定可用於表示bar1bar2的常見類型,或者重新組織代碼以便您根本不需要返回。

也就是說,如果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 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中使用operator(),只需將其專門化即可。

您可以定義兩個函數,其中只有一個函數將針對給定類型進行實例化:

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;
}

演示

您可以返回一個union類型,可以是T1T2

由於返回類型必須固定為編譯時,因此必須返回可以是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工作方式。


當然,正如大衛所說,如果在編譯時知道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在評論和沃爾特斯中所提到的那樣,如果這是您的偏好,那么返回參考也會有效。

Base& foo(MyClass<T1>& bar1, MyClass<T2>& bar2)
{
    if (something)
        return bar1;
    else
        return bar2;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM