#include <iostream>
#include <type_traits>
template <typename T>
using Return = typename std::conditional<std::is_rvalue_reference<T>::value, typename std::remove_reference<T>::type, T>::type;
template <typename T>
using CRef = typename std::remove_reference<T>::type const&;
template<typename Str>
Return<Str> StringReplace(Str&& str, CRef<Str> from, CRef<Str> to)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
if (std::is_same<std::string&&, decltype(str)>::value)
std::cout << "rvalue-ref\n\n";
else if (std::is_same<std::string&, decltype(str)>::value)
std::cout << "lvalue-ref\n\n";
return std::forward<Str>(str);
}
int main() {
std::string s1;
StringReplace(s1, "", "");
// Forwarding reference will deduce Str to std::string& when passing an lvalue
StringReplace<std::string&>(s1, "", "");
StringReplace(std::move(s1), "", "");
StringReplace<std::string>(std::move(s1), "", "");
StringReplace<std::string>("", "", "");
const std::string& test = s1;
StringReplace(test, "", "");
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KdXNpbmcgUmV0dXJuID0gdHlwZW5hbWUgc3RkOjpjb25kaXRpb25hbDxzdGQ6OmlzX3J2YWx1ZV9yZWZlcmVuY2U8VD46OnZhbHVlLCB0eXBlbmFtZSBzdGQ6OnJlbW92ZV9yZWZlcmVuY2U8VD46OnR5cGUsIFQ+Ojp0eXBlOwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnVzaW5nIENSZWYgPSB0eXBlbmFtZSBzdGQ6OnJlbW92ZV9yZWZlcmVuY2U8VD46OnR5cGUgY29uc3QmOwoKdGVtcGxhdGU8dHlwZW5hbWUgU3RyPgpSZXR1cm48U3RyPiBTdHJpbmdSZXBsYWNlKFN0ciYmIHN0ciwgQ1JlZjxTdHI+IGZyb20sIENSZWY8U3RyPiB0bykKewogICAgc3RkOjpjb3V0IDw8IF9fUFJFVFRZX0ZVTkNUSU9OX18gPDwgc3RkOjplbmRsOwogICAgaWYgKHN0ZDo6aXNfc2FtZTxzdGQ6OnN0cmluZyYmLCBkZWNsdHlwZShzdHIpPjo6dmFsdWUpCglzdGQ6OmNvdXQgPDwgInJ2YWx1ZS1yZWZcblxuIjsKICAgIGVsc2UgaWYgKHN0ZDo6aXNfc2FtZTxzdGQ6OnN0cmluZyYsIGRlY2x0eXBlKHN0cik+Ojp2YWx1ZSkKCXN0ZDo6Y291dCA8PCAibHZhbHVlLXJlZlxuXG4iOwogICAgcmV0dXJuIHN0ZDo6Zm9yd2FyZDxTdHI+KHN0cik7Cn0KCmludCBtYWluKCkgewoJc3RkOjpzdHJpbmcgczE7CgkKICAgICAgICAgICAgU3RyaW5nUmVwbGFjZShzMSwgIiIsICIiKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIEZvcndhcmRpbmcgcmVmZXJlbmNlIHdpbGwgZGVkdWNlIFN0ciB0byBzdGQ6OnN0cmluZyYgd2hlbiBwYXNzaW5nIGFuIGx2YWx1ZQogICAgICAgICAgICBTdHJpbmdSZXBsYWNlPHN0ZDo6c3RyaW5nJj4oczEsICIiLCAiIik7CiAgICAgICAgICAgIAogICAgICAgICAgICBTdHJpbmdSZXBsYWNlKHN0ZDo6bW92ZShzMSksICIiLCAiIik7CiAgICAgICAgICAgIAogICAgICAgICAgICBTdHJpbmdSZXBsYWNlPHN0ZDo6c3RyaW5nPihzdGQ6Om1vdmUoczEpLCAiIiwgIiIpOwogICAgICAgICAgICAKICAgICAgICAgICAgU3RyaW5nUmVwbGFjZTxzdGQ6OnN0cmluZz4oIiIsICIiLCAiIik7CiAgICAgICAgICAgIAogICAgICAgICAgICBjb25zdCBzdGQ6OnN0cmluZyYgdGVzdCA9IHMxOwoJU3RyaW5nUmVwbGFjZSh0ZXN0LCAiIiwgIiIpOwp9
Return<Str> StringReplace(Str&&, CRef<Str>, CRef<Str>) [with Str = std::__cxx11::basic_string<char>&; Return<Str> = std::__cxx11::basic_string<char>&; CRef<Str> = const std::__cxx11::basic_string<char>&; typename std::remove_reference< <template-parameter-1-1> >::type = std::__cxx11::basic_string<char>]
lvalue-ref
Return<Str> StringReplace(Str&&, CRef<Str>, CRef<Str>) [with Str = std::__cxx11::basic_string<char>&; Return<Str> = std::__cxx11::basic_string<char>&; CRef<Str> = const std::__cxx11::basic_string<char>&; typename std::remove_reference< <template-parameter-1-1> >::type = std::__cxx11::basic_string<char>]
lvalue-ref
Return<Str> StringReplace(Str&&, CRef<Str>, CRef<Str>) [with Str = std::__cxx11::basic_string<char>; Return<Str> = std::__cxx11::basic_string<char>; CRef<Str> = const std::__cxx11::basic_string<char>&; typename std::remove_reference< <template-parameter-1-1> >::type = std::__cxx11::basic_string<char>]
rvalue-ref
Return<Str> StringReplace(Str&&, CRef<Str>, CRef<Str>) [with Str = std::__cxx11::basic_string<char>; Return<Str> = std::__cxx11::basic_string<char>; CRef<Str> = const std::__cxx11::basic_string<char>&; typename std::remove_reference< <template-parameter-1-1> >::type = std::__cxx11::basic_string<char>]
rvalue-ref
Return<Str> StringReplace(Str&&, CRef<Str>, CRef<Str>) [with Str = std::__cxx11::basic_string<char>; Return<Str> = std::__cxx11::basic_string<char>; CRef<Str> = const std::__cxx11::basic_string<char>&; typename std::remove_reference< <template-parameter-1-1> >::type = std::__cxx11::basic_string<char>]
rvalue-ref
Return<Str> StringReplace(Str&&, CRef<Str>, CRef<Str>) [with Str = const std::__cxx11::basic_string<char>&; Return<Str> = const std::__cxx11::basic_string<char>&; CRef<Str> = const std::__cxx11::basic_string<char>&; typename std::remove_reference< <template-parameter-1-1> >::type = const std::__cxx11::basic_string<char>]