*this是否可以在成員函式中完美地轉發物件?如果是,那么我們該怎么做呢?如果不是,那為什么不呢?我們有什么替代方案才能達到同樣的效果。
請參閱下面的代碼片段以更好地理解問題。
class Experiment {
public:
double i, j;
Experiment(double p_i = 0, double p_j = 0) : i(p_i), j(p_j) {}
double sum() { return i j someConstant(); }
double someConstant() && { return 10; }
double someConstant() & { return 100; }
};
int main() {
Experiment E(3, 5);
std::cout << std::move(E).sum() << "\n"; // prints: 108
std::cout << E.sum() << "\n"; // prints: 108
}
如果我們認為*this成員函式內的物件double sum()始終是左值或 xvalue(因此是 glvalue),則此輸出似乎是預期的。請確認這是否屬實。
我們如何才能完美地將*this物件轉發給成員函式someConstant()內部的double sum()成員函式呼叫呢?
我嘗試使用std::forward如下:
double sum() {
return i j std::forward<decltype(*this)>(*this).someConstant();
}
但這沒有任何效果,并且double someConstant() &總是呼叫多載。
uj5u.com熱心網友回復:
sum如果不多載for&和&&限定符,這在 C 11 中是不可能的。(在這種情況下,您可以從特定多載的限定符中確定值類別。)
*this就像任何間接的結果一樣,是一個左值,也是呼叫隱式成員函式呼叫的物件。
這將在 C 23 中通過引入可以應用通常轉發的顯式物件引數來修復:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7。 html
uj5u.com熱心網友回復:
有人會認為這std::forward()會保留左值參考,但它們不會在非模板背景關系中,如下例所示。
兩者call_f()&都call_f()&&呼叫f()&&。std::forward<Experiment>(*this)在非模板函式中,無論引數的值類別如何,都會回傳一個右值參考。
請注意這與模板函式的作業方式有何不同,無論是否成員(我將成員函式設為靜態,因為它接收“this參考”作為顯式引數)。兩個前向左值都“正確”參考(最后 4 次呼叫)。
#include<iostream>
#include<utility>
#include<string>
struct Experiment
{
public:
std::string f()&& { return "f()&&"; }
std::string f()& { return "f()&"; }
std::string call_f()&& { std::cout << "call_f()&& "; return std::forward<Experiment>(*this).f(); }
// I need this function because it is not a template function
std::string call_f()& { std::cout << "call_f()& "; return std::forward<Experiment>(*this).f(); }
template<class T = Experiment>
static std::string E_t_call_f(T&& t) { std::cout << "E_t_call_f(T&& t) "; return std::forward<T>(t).f(); }
};
template<class T>
std::string t_call_f(T&& t) { std::cout << "t_call_f(T&& t) "; return std::forward<T>(t).f(); }
int main()
{
Experiment E;
std::cout << "E.f(): " << E.f() << '\n';
std::cout << "move(E).f(): " << std::move(E).f() << '\n';
std::cout << '\n';
std::cout << "E.call_f(): " << E.call_f() << '\n';
std::cout << "move(E).call_f(): " << std::move(E).call_f() << '\n';
std::cout << '\n';
std::cout << "t_call_f(E): " << t_call_f(E) << '\n';
std::cout << "t_call_f(std::move(E)): " << t_call_f(std::move(E)) << '\n';
std::cout << '\n';
std::cout << "E::E_t_call_f(E): " << Experiment::E_t_call_f(E) << '\n';
std::cout << "E::E_t_call_f(std::move(E)): " << Experiment::E_t_call_f(std::move(E)) << '\n';
}
在結果輸出中,令人驚訝的是第三行:std::forward<Experiment>(*this)左值參考的型別*this 是右值參考。
E.f(): f()&
move(E).f(): f()&&
call_f()& E.call_f(): f()&&
call_f()&& move(E).call_f(): f()&&
t_call_f(T&& t) t_call_f(E): f()&
t_call_f(T&& t) t_call_f(std::move(E)): f()&&
E_t_call_f(T&& t) E::E_t_call_f(E): f()&
E_t_call_f(T&& t) E::E_t_call_f(std::move(E)): f()&&
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/437746.html
下一篇:遍歷所有結構成員
