[英]C++ cascaded operator[] to operator() parameter list?
我有一個帶有operator()
的類,如下所示:
struct S
{
int operator()(int a, int b, int c, int d);
};
用法示例:
S s;
int i = s(1, 2, 3, 4);
我需要我的用戶能夠使用其他語法:
int i = s[1][2][3][4]; // equivalent to calling s(1, 2, 3, 4)
我知道我需要添加S::operator[](int a)
,並且它需要返回一個輔助對象。 但是除此之外,這一切都變得有些復雜,我覺得我正在重新發明輪子,因為其他庫(例如多維數組)可能已經提供了類似的接口。
理想情況下,我只會使用現有的庫來實現此目標。 失敗了,如何用最通用的代碼實現我的目標?
編輯:理想情況下,我希望在現代優化編譯器上實現此目標而不會增加運行時間。
開始了!
首先,代碼有點雜亂無章-我必須在執行過程中累積參數值,而我能想到的唯一方法(至少在C ++ 03中是)將立即索引集作為數組傳遞。
我已經在G ++ 4.5.1(Windows / MinGW)上進行了檢查,並確認在-O3上進行了調用:
s[1][2][3][4];
產生與以下代碼相同的匯編代碼:
s(1,2,3,4);
因此-如果您的編譯器很聰明且具有優化功能,則不會產生運行時開銷。 干得好,GCC團隊!
代碼如下:
#include <iostream>
template<typename T, unsigned N, unsigned Count>
struct PartialResult
{
static const int IndicesRemembered = Count-1-N;
T& t;
int args[IndicesRemembered];
PartialResult(T& t, int arg, const int* rest) : t(t) {
for (int i=0; i<IndicesRemembered-1; ++i) {
args[i] = rest[i];
}
if (IndicesRemembered>0) args[IndicesRemembered-1] = arg;
}
PartialResult<T, N-1, Count> operator[](int k) {
return PartialResult<T, N-1, Count>(t, k, args);
}
};
template<typename T, unsigned Count>
struct PartialResult<T, 0, Count>
{
static const int IndicesRemembered = Count-1;
T& t;
int args[IndicesRemembered];
PartialResult(T& t, int arg, const int* rest) : t(t) {
for (int i=0; i<IndicesRemembered-1; ++i) {
args[i] = rest[i];
}
if (IndicesRemembered>0) args[IndicesRemembered-1] = arg;
}
void operator[](int k) {
int args2[Count];
for (int i=0; i<Count-1; ++i) {
args2[i] = args[i];
}
args2[Count-1] = k;
t(args2);
}
};
template<typename T, unsigned Count>
struct InitialPartialResult : public PartialResult<T, Count-2, Count> {
InitialPartialResult(T& t, int arg)
: PartialResult<T, Count-2, Count>(t, arg, 0) {}
};
struct C {
void operator()(const int (&args)[4]) {
return operator()(args[0], args[1], args[2], args[3]);
}
void operator()(int a, int b, int c, int d) {
std::cout << a << " " << b << " " << c << " " << d << std::endl;
}
InitialPartialResult<C, 4> operator[](int m) {
return InitialPartialResult<C, 4>(*this, m);
}
};
嚴重的是,請不要使用它,而要堅持使用operator()
。 :)干杯!
我會完全避免這種情況,只提供operator()
,但是如果您真的想試一試,則想法是您類型的operator[]
將返回一個同時具有對您的對象和對象的引用的輔助類型的對象。傳入的值。該幫助程序類將通過再次存儲對原始對象的引用以及對[]
兩次調用的參數來實現operator[]
[]
。 除最后一個級別(即大量的助手)外,所有其他人都必須這樣做。 在最后一級, operator[]
將其參數與所有先前存儲的值一起使用,並與所有先前存儲的值加當前值一起調用operator()
。
短語的一種常用說法是,每個中間類型都將對operator()
的調用的參數之一綁定 ,而最后一個對所有綁定的參數執行該調用。
根據是否要支持更多或更少數量的數組維數,您可能希望/需要使其復雜化以使其通用。 通常,不值得付出努力,僅提供operator()
通常是解決方案。 請記住,最好使事情盡可能簡單:減少編寫工作的精力,而減少維護工作的精力。
這是對bind
方法的嘗試。 我懷疑它是否特別有效,並且其中包含一些令人討厭的內容,但如果有人知道如何修復它,我會發布它。 請編輯:
template <int N>
struct Helper {
function_type<N>::type f;
explicit Helper(function_type<N>::type f) : f(f) {}
Helper<N-1> operator[](int p) {
return Helper<N-1>(bound<N-1>(f,p));
}
};
template<>
struct Helper<0> {
function_type<0>::type f;
explicit Helper(function_type<0>::type f) : f(f) {}
operator int() {
return f();
}
};
Helper<3> S::operator[](int p) {
return Helper<3>(std::bind(s, _1, _2, _3));
}
其中s
是一個表達式,該表達式返回綁定到this
operator()
。 std::bind(std::mem_fun(S::operator(), this, _1, _2, _3, _4))
。 盡管我不記得std::bind
是否已經可以處理成員函數,但可能不需要mem_fun
。
function_type<N>::type
為std::function<int, [int, ... n times]>
, bound<N>
為function_type<N>::type bound(function_type<N+1>::type f, int p) { return std::bind(f, p, _1, _2, ... _N); }
function_type<N>::type bound(function_type<N+1>::type f, int p) { return std::bind(f, p, _1, _2, ... _N); }
。 我不確定如何遞歸地定義它們,但是您可以列出它們的上限。
這是一個Fusion實現,支持任意參數和返回類型。 對任何可以使用此功能的人都表示感謝(如果可以,請告訴我)!
template <class Derived, class ReturnValue, class Sequence>
struct Bracketeer
{
typedef ReturnValue result_type;
typedef boost::fusion::result_of::size<Sequence> Size;
struct RvBase
{
Sequence sequence;
Derived *derived;
};
template <int n>
struct Rv : RvBase
{
Rv(Derived *d) { this->derived = d; }
Rv(RvBase *p) : RvBase(*p) { }
Rv<n-1> operator[](typename boost::fusion::result_of::at_c<Sequence const, n-1>::type v)
{
boost::fusion::at_c<Size::value - 1 - n>(sequence) = v;
return Rv<n-1>(this);
}
};
template <>
struct Rv<0> : RvBase
{
Rv(Derived *d) { this->derived = d; }
Rv(RvBase *p) : RvBase(*p) { }
ReturnValue operator[](typename boost::fusion::result_of::at_c<Sequence, Size::value - 1>::type v)
{
boost::fusion::at_c<Size::value - 1>(sequence) = v;
return invoke(*derived, sequence);
}
};
Rv<Size::value - 1> operator[](typename boost::fusion::result_of::at_c<Sequence, 0>::type v)
{
Rv<Size::value> rv(static_cast<Derived*>(this));
return rv[v];
}
};
struct S
:
Bracketeer<S, int, boost::fusion::vector<int, int, int, int> >
{
int operator()(int a, int b, int c, int d);
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.