如何组合就地转换和复制转换?

Tre*_*key 4 c++ templates overloading function c++17

我想将这两个功能组合到一个功能界面中:

T& Transform(T & foo){
   //transform t
   return t;
}

T As_Transformed(T foo){
   //transform t
   return t;
}
Run Code Online (Sandbox Code Playgroud)

有时我想转换传递给函数的变量.
其他时候我想要一个带有应用转换的新变量.

结果,我最终每次都创建了两个函数,并遵循我的一个简单的约定,其中As_take并返回一个副本,而没有As_take并返回一个引用.

如何编写一个能够处理这两种行为的单一函数实现?

我对它应该是什么样子没有任何要求,但我想有一种方法,我不依赖于我的As_约定,理想情况下我只做一个函数而不是两个.


示例:
以下是此示例的示例.
让我们Uppercase()As_Upercased()

std::string str1 = "hello";
Uppercase(str1); //str is now "HELLO"

std::string str2 = "hello";
auto str3 = As_Uppercased(str2); //str2 is still "hello", 
                                 //but str3 is "HELLO"
Run Code Online (Sandbox Code Playgroud)

我不知道组合界面会是什么样子,但也许:

std::string str1 = "hello";
Uppercase<REF>(str1); //str is now "HELLO"

std::string str2 = "hello";
auto str3 = Uppercase<COPY>(str2); //str2 is still "hello", 
                                   //but str3 is "HELLO"
Run Code Online (Sandbox Code Playgroud)

或者也许我可以用引用包装器做一些事情.
我正在询问的可能的实现方式.

Ros*_*lav 7

您可以通过提供重载来告诉编译器如何区分这两者std::reference_wrapper.然后代码看起来像这样,例如:

#include <iostream>
#include <functional>

using T = std::string;

T Transform(T t)
{
    t += " copy";
    return t;
}

std::reference_wrapper<T> Transform(std::reference_wrapper<T> t)
{
    t.get() += " ref";
    return t;
}

int main()
{
    T t{"original"};

    std::cout << Transform(Transform(t)) << "\n";
    std::cout << t << "\n";
    std::cout << Transform(Transform(std::ref(t))).get() << "\n";
    std::cout << t;
}
Run Code Online (Sandbox Code Playgroud)

输出:

original copy copy
original
original ref ref
original ref ref
Run Code Online (Sandbox Code Playgroud)

请注意,原始值在第一个调用链之后如何保持不变,并在第二个调用链之后进行修改.

在您的实际代码中,第一个重载只会调用第二个重载来转换其包装的pass-by-copy参数,std::ref以避免代码重复.

生活