c++ - 如何在不使用模板的情况下进行完美转发?

标签 c++ c++11

我想要完美转发,但我已经知道(并且只接受)我的函数将采用的类型。

这是我输入的一个简单示例:

class big_class
{
private:
    std::string m_somethingBig;
};

class testmove
{
public:

    void Add(big_class&& big)
    {
        std::cout << "Add via move\n";
        m_bigClasses.push_back(std::move(big));
    }

    void Add(big_class const& big)
    {
        std::cout << "Add via copy\n";
        m_bigClasses.push_back(big);
    }

private:

    std::vector<big_class> m_bigClasses;
};

int main()
{
    testmove tm;

    big_class big;
    tm.Add(big);

    tm.Add(big_class{});
}

Live Sample

是否可以在 testmove::Add() 的两个重载之间进行某种形式的实现共享?我想优化移动,如果有人在没有我的右值重载的情况下执行 std::move(),它最终会在添加到我的 vector 之前至少执行 1 个拷贝。

再次,我意识到我可以通过使 Add() 成为模板函数,甚至使用类型特征和一些模板技巧来解决这个问题。但我想尽可能避免这种情况。如果你需要知道为什么,我有几个原因:

  • 我无法使用模板隐藏实现(限制单个翻译单元的包含和符号可见性)
  • 在这里使用模板比我想要的更灵活(我的契约(Contract)要求我只使用 big_class)。
  • 使用模板会影响本应是简单界面的可读性/可维护性。

最佳答案

Xeo 建议的方法(按值获取参数)是我强烈推荐的方法。但是,如果由于某种原因您不能这样做(例如,移动很昂贵,但比复制要便宜),请继续阅读。

我认为有可能满足您的所有标准,但只有当代码足够复杂以至于复制它会很糟糕时才值得。这个想法是委托(delegate)给一个模板,该模板将仅为 big_class 显式实例化。

big_class.h:

// ...
public:
    void Add(big_class&& big)
    {
        Add_internal(std::move(big));
    }
    void Add(big_class const& big)
    {
        Add_internal(big);
    }
private:
    // not part of interface; defined in .cpp file
    template <typename T> void Add_internal(T&& big);

big_class.cpp:

// implementation of template
template <typename T> void big_class::Add_internal(T&& big) {
    // shared logic goes here
    m_bigClasses.push_back(std::forward<T>(big));
}
// explicit instantiation
template void big_class::Add_internal<big_class>(big_class&&);
template void big_class::Add_internal<big_class const&>(big_class const&);

关于c++ - 如何在不使用模板的情况下进行完美转发?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36365418/

相关文章:

c++ - std::ofstream 是可移动的吗?

c++ - is_constexpr 在 C++11 中是否可行?

c++ - 视觉 C++ : Linking a DLL from another DLL using a relative path

c++ - 使用 Windows API 和 WM_KEYDOWN C++ 时按键输入滞后

C++ 析构函数 : when the memory gets freed?

header 中的 C++ 数组

指针存储在容器中的对象的 C++ 分配器

c++11 - 在 C++11 及更高版本中,常量引用仍然是最佳实践吗?

c++ - 在 typeid(SOME_TYPE).name() 中返回别名标识符而不是类型

c++ - c++11(工作草案)标准中的布局兼容性是否太弱?