#include <iostream>
#include <type_traits>
#include <string>
#include <limits>
template<typename T>
using StringReplaceIsInPlace = std::conditional_t<std::is_lvalue_reference<T>::value && !std::is_const<std::remove_reference_t<T>>::value, std::true_type, std::false_type>;
template<typename Str, typename = std::enable_if_t<StringReplaceIsInPlace<Str>::value>>
Str StringReplace(
Str&& str,
const std::remove_reference_t<Str>& from,
const std::remove_reference_t<Str>& to
) {
std::cout << "in place: " << __PRETTY_FUNCTION__ << std::endl;
return std::forward<Str>(str);
}
template<typename Str, typename = std::enable_if_t<!StringReplaceIsInPlace<Str>::value>>
std::decay_t<Str> StringReplace(
Str&& str, // const lvalues and rvalues
const std::remove_reference_t<Str>& from,
const std::remove_reference_t<Str>& to
) {
std::cout << "in a copy: " << __PRETTY_FUNCTION__ << std::endl;
std::decay_t<Str> mutableStr{std::forward<Str>(str)};
StringReplace(mutableStr, from, to);
return mutableStr;
}
int main()
{
{
std::cout << "lvalue" << std::endl;
std::string v;
StringReplace(v, "", "");
}
{
std::cout << std::endl << "const lvalue" << std::endl;
const std::string v;
StringReplace(v, "", "");
}
{
std::cout << std::endl << "lvalue reference" << std::endl;
std::string v;
std::string& vref = v;
StringReplace(vref, "", "");
}
{
std::cout << std::endl << "const lvalue reference" << std::endl;
std::string v;
const std::string& vref = v;
StringReplace(vref, "", "");
}
{
std::cout << std::endl << "rvalue" << std::endl;
std::string v;
StringReplace(std::move(v), "", "");
}
{
std::cout << std::endl << "const rvalue" << std::endl;
const std::string v;
StringReplace(std::move(v), "", "");
}
{
std::cout << std::endl << "rvalue reference" << std::endl;
std::string&& v = std::string();
StringReplace(v, "", "");
}
{
std::cout << std::endl << "const rvalue reference" << std::endl;
const std::string&& v = std::string();
StringReplace(v, "", "");
}
{
std::cout << std::endl << "string literal" << std::endl;
StringReplace<std::string>("", "", "");
}
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDxsaW1pdHM+Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgp1c2luZyBTdHJpbmdSZXBsYWNlSXNJblBsYWNlID0gc3RkOjpjb25kaXRpb25hbF90PHN0ZDo6aXNfbHZhbHVlX3JlZmVyZW5jZTxUPjo6dmFsdWUgJiYgIXN0ZDo6aXNfY29uc3Q8c3RkOjpyZW1vdmVfcmVmZXJlbmNlX3Q8VD4+Ojp2YWx1ZSwgc3RkOjp0cnVlX3R5cGUsIHN0ZDo6ZmFsc2VfdHlwZT47Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBTdHIsIHR5cGVuYW1lID0gc3RkOjplbmFibGVfaWZfdDxTdHJpbmdSZXBsYWNlSXNJblBsYWNlPFN0cj46OnZhbHVlPj4KU3RyIFN0cmluZ1JlcGxhY2UoCiAgICBTdHImJiBzdHIsCiAgICBjb25zdCBzdGQ6OnJlbW92ZV9yZWZlcmVuY2VfdDxTdHI+JiBmcm9tLAogICAgY29uc3Qgc3RkOjpyZW1vdmVfcmVmZXJlbmNlX3Q8U3RyPiYgdG8KKSB7CiAgICBzdGQ6OmNvdXQgPDwgImluIHBsYWNlOiAiIDw8IF9fUFJFVFRZX0ZVTkNUSU9OX18gPDwgc3RkOjplbmRsOwogICAgcmV0dXJuIHN0ZDo6Zm9yd2FyZDxTdHI+KHN0cik7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFN0ciwgdHlwZW5hbWUgPSBzdGQ6OmVuYWJsZV9pZl90PCFTdHJpbmdSZXBsYWNlSXNJblBsYWNlPFN0cj46OnZhbHVlPj4Kc3RkOjpkZWNheV90PFN0cj4gU3RyaW5nUmVwbGFjZSgKICAgIFN0ciYmIHN0ciwgLy8gY29uc3QgbHZhbHVlcyBhbmQgcnZhbHVlcwogICAgY29uc3Qgc3RkOjpyZW1vdmVfcmVmZXJlbmNlX3Q8U3RyPiYgZnJvbSwKICAgIGNvbnN0IHN0ZDo6cmVtb3ZlX3JlZmVyZW5jZV90PFN0cj4mIHRvCikgewogICAgc3RkOjpjb3V0IDw8ICJpbiBhIGNvcHk6ICIgPDwgX19QUkVUVFlfRlVOQ1RJT05fXyA8PCBzdGQ6OmVuZGw7CiAgICBzdGQ6OmRlY2F5X3Q8U3RyPiBtdXRhYmxlU3Rye3N0ZDo6Zm9yd2FyZDxTdHI+KHN0cil9OwogICAgU3RyaW5nUmVwbGFjZShtdXRhYmxlU3RyLCBmcm9tLCB0byk7CiAgICByZXR1cm4gbXV0YWJsZVN0cjsKfQoKaW50IG1haW4oKQp7CiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8ICJsdmFsdWUiIDw8IHN0ZDo6ZW5kbDsKICAgICAgICBzdGQ6OnN0cmluZyB2OwogICAgICAgIFN0cmluZ1JlcGxhY2UodiwgIiIsICIiKTsKICAgIH0KCiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbCA8PCAiY29uc3QgbHZhbHVlIiA8PCBzdGQ6OmVuZGw7CiAgICAgICAgY29uc3Qgc3RkOjpzdHJpbmcgdjsKICAgICAgICBTdHJpbmdSZXBsYWNlKHYsICIiLCAiIik7CiAgICB9CiAgICAKICAgIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgc3RkOjplbmRsIDw8ICJsdmFsdWUgcmVmZXJlbmNlIiA8PCBzdGQ6OmVuZGw7CiAgICAgICAgc3RkOjpzdHJpbmcgdjsKICAgICAgICBzdGQ6OnN0cmluZyYgdnJlZiA9IHY7CiAgICAgICAgU3RyaW5nUmVwbGFjZSh2cmVmLCAiIiwgIiIpOwogICAgfQoKICAgIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgc3RkOjplbmRsIDw8ICJjb25zdCBsdmFsdWUgcmVmZXJlbmNlIiA8PCBzdGQ6OmVuZGw7CiAgICAgICAgc3RkOjpzdHJpbmcgdjsKICAgICAgICBjb25zdCBzdGQ6OnN0cmluZyYgdnJlZiA9IHY7CiAgICAgICAgU3RyaW5nUmVwbGFjZSh2cmVmLCAiIiwgIiIpOwogICAgfQogICAgCiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbCA8PCAicnZhbHVlIiA8PCBzdGQ6OmVuZGw7CiAgICAgICAgc3RkOjpzdHJpbmcgdjsKICAgICAgICBTdHJpbmdSZXBsYWNlKHN0ZDo6bW92ZSh2KSwgIiIsICIiKTsKICAgIH0KCiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbCA8PCAiY29uc3QgcnZhbHVlIiA8PCBzdGQ6OmVuZGw7CiAgICAgICAgY29uc3Qgc3RkOjpzdHJpbmcgdjsKICAgICAgICBTdHJpbmdSZXBsYWNlKHN0ZDo6bW92ZSh2KSwgIiIsICIiKTsKICAgIH0KCiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbCA8PCAicnZhbHVlIHJlZmVyZW5jZSIgPDwgc3RkOjplbmRsOwogICAgICAgIHN0ZDo6c3RyaW5nJiYgdiA9IHN0ZDo6c3RyaW5nKCk7CiAgICAgICAgU3RyaW5nUmVwbGFjZSh2LCAiIiwgIiIpOwogICAgfQoKICAgIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgc3RkOjplbmRsIDw8ICJjb25zdCBydmFsdWUgcmVmZXJlbmNlIiA8PCBzdGQ6OmVuZGw7CiAgICAgICAgY29uc3Qgc3RkOjpzdHJpbmcmJiB2ID0gc3RkOjpzdHJpbmcoKTsKICAgICAgICBTdHJpbmdSZXBsYWNlKHYsICIiLCAiIik7CiAgICB9CgogICAgewogICAgICAgIHN0ZDo6Y291dCA8PCBzdGQ6OmVuZGwgPDwgInN0cmluZyBsaXRlcmFsIiA8PCBzdGQ6OmVuZGw7CiAgICAgICAgU3RyaW5nUmVwbGFjZTxzdGQ6OnN0cmluZz4oIiIsICIiLCAiIik7CiAgICB9CiAgICAKCXJldHVybiAwOwp9
lvalue
in place: Str StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::remove_reference_t<T> = std::__cxx11::basic_string<char>]
const lvalue
in a copy: std::decay_t<Str> StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = const std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::decay_t<Str> = std::__cxx11::basic_string<char>; std::remove_reference_t<T> = const std::__cxx11::basic_string<char>]
in place: Str StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::remove_reference_t<T> = std::__cxx11::basic_string<char>]
lvalue reference
in place: Str StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::remove_reference_t<T> = std::__cxx11::basic_string<char>]
const lvalue reference
in a copy: std::decay_t<Str> StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = const std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::decay_t<Str> = std::__cxx11::basic_string<char>; std::remove_reference_t<T> = const std::__cxx11::basic_string<char>]
in place: Str StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::remove_reference_t<T> = std::__cxx11::basic_string<char>]
rvalue
in a copy: std::decay_t<Str> StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = std::__cxx11::basic_string<char>; <template-parameter-1-2> = void; std::decay_t<Str> = std::__cxx11::basic_string<char>; std::remove_reference_t<T> = std::__cxx11::basic_string<char>]
in place: Str StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::remove_reference_t<T> = std::__cxx11::basic_string<char>]
const rvalue
in a copy: std::decay_t<Str> StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = const std::__cxx11::basic_string<char>; <template-parameter-1-2> = void; std::decay_t<Str> = std::__cxx11::basic_string<char>; std::remove_reference_t<T> = const std::__cxx11::basic_string<char>]
in place: Str StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::remove_reference_t<T> = std::__cxx11::basic_string<char>]
rvalue reference
in place: Str StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::remove_reference_t<T> = std::__cxx11::basic_string<char>]
const rvalue reference
in a copy: std::decay_t<Str> StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = const std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::decay_t<Str> = std::__cxx11::basic_string<char>; std::remove_reference_t<T> = const std::__cxx11::basic_string<char>]
in place: Str StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::remove_reference_t<T> = std::__cxx11::basic_string<char>]
string literal
in a copy: std::decay_t<Str> StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = std::__cxx11::basic_string<char>; <template-parameter-1-2> = void; std::decay_t<Str> = std::__cxx11::basic_string<char>; std::remove_reference_t<T> = std::__cxx11::basic_string<char>]
in place: Str StringReplace(Str&&, std::remove_reference_t<T>&, std::remove_reference_t<T>&) [with Str = std::__cxx11::basic_string<char>&; <template-parameter-1-2> = void; std::remove_reference_t<T> = std::__cxx11::basic_string<char>]