lvalue: loactor value
rvalue: read value
here is an example of class definition with only one constructor using template and 'forward' technique to tackle varying parameter:
rvalue.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | #include <iostream> #include <functional> using namespace std; template <typename T> constexpr bool is_lvalue(T&) { return true; } template <typename T> constexpr bool is_lvalue(T&&) { return false; } class MyStr { public: template<class T> MyStr(T&& t) { set(forward<T>(t)); } template<class T> void set(T&& t) { if constexpr (conjunction_v<is_convertible<T&, MyStr&>>) { if (!is_lvalue(forward<T>(t))) { str_ = forward<string>(t.str_); cout << "is rvalue, type MyStr." << endl; } else { str_ = t.str_; cout << "is lvalue, type MyStr." << endl; } } else { str_ = forward<T>(t); cout << "is string." << endl; } } template<class T=char> void test() { cout << "test T size is " << sizeof(T) << endl; } string str_; }; int main() { cout << "call constructor:" << endl; MyStr str1("str1"); MyStr str2(str1); MyStr str3(move(str1)); cout << "call member function:" << endl; str1.set("set1"); str2.set(str1); str3.set(move(str1)); str3.test(); return 1; } |
make
1 | g++ -o rvalue -g -O0 -std=c++17 rvalue.cpp |
output
1 2 3 4 5 6 7 8 | call constructor:
is string.
is lvalue, type MyStr.
call member function:
is string.
is lvalue, type MyStr.
is rvalue, type MyStr.
test T size is 1 |
refer to:
http://www.javashuo.com/article/p-olwxiggw-q.html
http://c.biancheng.net/view/7829.html
https://zhuanlan.zhihu.com/p/99524127