0

与底部相比,使用以下内容有什么优势吗?还有其他方法可以创建模板函数别名吗?

template <typename T, typename... Args>
auto MakeShared(Args&&... args) -> decltype(std::make_shared<T>(std::forward<Args>(args)...)) 
{
    return std::make_shared<T>(std::forward<Args>(args)...);
}

和:

template <typename T, typename... Args>
inline SharedPtr<T> MakeShared(Args&&... args)
{
    return std::make_shared<T>(args...);
}

最后一个对我来说似乎更具可读性,而且,Visual Assist 突出显示内联版本就像一个正确的函数,但似乎对第一个感到困惑(是的,我知道这是一个小问题,但仍然如此)。

性能、灵活性等呢?

4

1 回答 1

2

您不能给函数起别名,您可以编写将实际工作转发给现有函数的新函数,但您不能只提供别名。

现在,还不清楚真正的问题是什么。对于初学者,我不会围绕标准库功能编写包装器,因为那只会使您的代码更加晦涩难懂。无论您喜欢std::make_shared更好或更坏MakeShared,前者对于任何 C++ 程序员来说都是众所周知的,而前者是需要查找的不明显的东西。(而且我个人不喜欢以大写字母开头的函数名称,但这是一个不同的问题)。

如果问题是关于实现的,考虑到您已经知道包装器的返回类型,我不会使用 decltype,这确实使代码更加晦涩难懂。但是使用它仍然很重要std::forward

template <typename T, typename... Args>
std::shared_ptr<T> MakeShared(Args&&... args)
{
    return std::make_shared<T>(std::forward<Args>(args)...);
}

添加尾随返回类型和decltypewhen 类型更容易编写并且完全不依赖于参数是荒谬的无缘无故地输入。std::forward需要提供模板参数的完美转发。否则,您最终可能会调用不正确版本的构造函数:

std::string f();
auto p = std::make_shared<std::string>(f());
    // calls std::string(std::string &&)
auto q = MakeShared<std::string>(f());          // assume no std::forward was used
    // calls std::string(std::string const &)

没有std::forward在实现中MakeShared作为参数传递给函数的右值将作为左值转发,导致分配新字符串、复制数据并最终在完整语句的末尾释放旧字符串。使用std::forward,新分配的std::string移出参数字符串。

于 2013-10-24T17:38:20.853 回答