gpt4 book ai didi

c++ - const 和通用引用的重载是否必要?

转载 作者:太空狗 更新时间:2023-10-29 23:52:44 25 4
gpt4 key购买 nike

考虑一个用于检查参数值等的“契约(Contract)”函数:

  template< class T >
const T& AssertNotEmpty( const T& val )
{
//raise hell if val empty/0/...
return val;
}

例如可以按如下方式使用:

void foo( const std::shared_ptr< int >& val )
{
AssertNotEmpty( val );
//use *val
}

class Bar98
{
public:
Bar98( const std::shared_ptr< int >& val ) : myVal( AssertNotEmpty( val ) ) {}
private:
std::shared_ptr< int > myVal;
};

std::shared_ptr< int > x;
//...
AssertNotEmpty( x ); //(1)

现在进入 C++11,我们希望 Bar98 按值获取构造函数参数并从中移动:

class Bar11
{
public:
Bar11( std::shared_ptr< int > val ) :
myVal( AssertNotEmpty( std::move( val ) ) )
{}
private:
std::shared_ptr< int > myVal;
};

为此,AssertNotEmpty 需要重写,我天真地认为可以通过使用通用引用来实现:

  template< class T >
T&& AssertNotEmpty( T&& val )
{
//...
return std::move( val );
}

除了最后一个 (1),这似乎适用于所有情况,其中 VS 给出 warning C4239: nonstandard extension used : 'return' : conversion from 'std::shared_ptr<int>' to 'std::shared_ptr<int> &' .据我所知,这是因为编译器看到了 AssertNotEmpty( x )这是 AssertNotEmpty( T& && x )折叠成 AssertNotEmpty( T& )你不能从 T& 移动,如有错误请指正。

为了解决这个问题,我添加了通用引用作为仅对非左值引用启用的重载,以强制编译器在遇到像 (1) 中那样的普通左值引用时也选择 const 引用:

  template< class T >
const T& AssertNotEmpty( const T& val )
{
//...
return val;
}

template< class T >
T&& AssertNotEmpty( T&& val, typename std::enable_if< !std::is_lvalue_reference< T >::value, int >::type* = 0 )
{
//...
return std::move( val );
}

似乎按预期工作,编译器在我尝试的所有情况下都选择了正确的,但这是解决此问题的“正确”C++11 方法吗?有什么可能的陷阱吗?有没有不需要重复的解决方案?

最佳答案

我认为您不应该从该函数返回任何内容。但是,这可能会如您所愿。

template<class T>
auto AssertNotEmpty(T&& val) -> decltype(std::forward<T>(val))
{
//...
return std::forward<T>(val);
}

关于c++ - const 和通用引用的重载是否必要?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14238429/

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