我想要完美转发,但我已经知道(并且只接受)我的函数将采用的类型。
这是我输入的一个简单示例:
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{});
}
是否可以在 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/