gpt4 book ai didi

c++ - std::make_unique SFINAE 友好吗?

转载 作者:太空狗 更新时间:2023-10-29 20:22:40 24 4
gpt4 key购买 nike

我正在做一些模板元编程,我想实现一个通用的克隆函数,它通过 SFINAE(替换失败不是错误)根据表达式的有效性选择克隆方法。

关于 this reference website它说

The function

make_unique<T>( std::forward<Args>(args)... )

is equivalent to:

unique_ptr<T>(new T(std::forward<Args>(args)...))

这是否意味着下面的代码

template <typename T>
auto my_clone( const T & t ) -> decltype( std::make_unique<T>(t) )
{
return std::make_unique<T>(t);
}

应该完全等同于

template <typename T>
auto my_clone( const T & t ) -> decltype( std::unique_ptr<T>( new T(t) ) )
{
return std::unique_ptr<T>( new T(t) );
}

即使我有函数 my_clone 的其他重载?换句话说:是 std::make_unique() SFINAE-friendly

如果 T不可复制构造的,则由于 SFINAE,后面的代码将不会参与重载决议。

这是一个小例子,它在启用 C++14 的情况下无法在 GCC 5.3 上编译:

#include <memory>

// It does **not** work with this snippet:
template <typename T>
auto my_clone( const T & t ) -> decltype( std::make_unique<T>( t ) )
{
return std::make_unique<T>( t );
}

/* // But it works with this snippet instead:
template <typename T>
auto my_clone( const T & t ) -> decltype( std::unique_ptr<T>( new T(t) ) )
{
return std::unique_ptr<T>( new T(t) );
}*/

// This is another overload for testing purposes.
template <typename T>
auto my_clone( const T & t ) -> decltype(t.clone())
{
return t.clone();
}

class X
{
public:
X() = default;

auto clone() const
{
return std::unique_ptr<X>( new X(*this) );
}

private:
X( const X & ) = default;
};

int main()
{
// The following line produces the compiler error:
// "call to 'my_clone' is ambiguous"
const auto x_ptr = my_clone( X() );
}

最佳答案

该标准仅保证:

template <class T, class... Args> unique_ptr<T> std::make_unique(Args&&... args);

...必须返回 unique_ptr<T>(new T(std::forward<Args>(args)...)) , 它不保证 make_unique函数应该只存在于T可以使用 Args... 构建,所以它不是 SFINAE 友好的(根据标准),所以你不能依赖它。

标准中唯一提到 make_unique 的部分:

§20.8.1.4 [unique.ptr.create]:

template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
  1. Remarks: This function shall not participate in overload resolution unless T is not an array.
  2. Returns: unique_ptr<T>(new T(std::forward<Args>(args)...)).

在您的情况下,您可能希望使用带有 std::unique_ptr<T>(new T(...)) 的版本或使用 is_copy_constructible让你的my_clone SFINAE 友好(@Yakk,@Jarod42),例如:

template <typename T,
typename = std::enable_if_t<std::is_copy_constructible<T>::value>>
auto my_clone(const T & t) -> decltype(std::make_unique<T>(t)) {
return std::make_unique<T>(t);
}

关于c++ - std::make_unique SFINAE 友好吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36915131/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com