【问题标题】:Cast a value using decltype, is it possible?使用 decltype 转换一个值,这可能吗?
【发布时间】:2013-05-22 08:38:10
【问题描述】:

是否可以使用 decltype 来转换一个值?

例如,假设我们有以下模板:

template<typename Container>
auto findInposition(Container& c,int position)->decltype(*(c.begin()))
{
  if(std::distance(c.begin(),c.begin()+position)<c.size())
  return c.at(p);
  /*else
    return decltype(*(c.begin())(somevalue);*/
}

它返回容器中特定position 处的项目的值。假设用户输入的位置大于容器的大小,在这种情况下,我想返回一个强制转换的值,比如说一个强制转换的零或其他东西。我不知道我的例子是否足够好,我的主要问题是:是否可以使用 decltype 来转换值,如果可以,如何转换?

【问题讨论】:

  • 是的,但您需要更改类型。到目前为止,它是一个非常量引用。

标签: c++ templates c++11 decltype


【解决方案1】:

一般来说,你可以做到。例如:

int i = 0;
double d = 3.14;
i = static_cast<decltype(i)>(d);

但是,请记住您的函数返回一个引用(因为decltype(*(c.begin())) 计算为引用类型):

std::vector<int> v;
static_assert(std::is_same<decltype(*v.begin()), int&>::value, "!"); // Won't fire

在这种情况下麻烦的是该函数必须能够返回对Container::value_type类型对象的引用,但是如果somevalue具有不同的类型,您将无法返回对它的引用作为Container::value_type&amp;

原因与不允许您执行以下操作的原因相同:

int i = 42;
float& f = static_cast<float&>(i);

所以你需要问自己的第一件事是你的findInposition() 函数是否真的应该返回对集合元素的引用(在这种情况下,你想要做的事情是不可能的,就像上面的例子一样) ,或者更确切地说按值返回该元素的副本。

如果是这样,并且你坚持使用decltype,你可以将decltype的输出转换为std::decay

#include <type_traits>

template<typename Container>
auto findInposition(Container& c,int position) ->
    typename std::decay<decltype(*c.begin())>::type
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
  if(std::distance(c.begin(),c.begin()+position)<c.size())
    return c.at(position);
  else
    return static_cast<
        typename std::decay<decltype(*c.begin())>::type>(somevalue);
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}

但在我看来,以下内容要清楚得多:

template<typename Container>
auto findInposition(Container& c,int position) ->
    typename Container::value_type
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
  if(std::distance(c.begin(),c.begin()+position)<c.size())
    return c.at(position);
  else
    return static_cast<typename Container::value_type>(somevalue);
//                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}

【讨论】:

  • @AvraamMavridis:很高兴它有帮助:)
猜你喜欢
  • 1970-01-01
  • 2022-09-27
  • 1970-01-01
  • 1970-01-01
  • 2012-10-13
  • 1970-01-01
  • 1970-01-01
  • 2020-05-17
  • 1970-01-01
相关资源
最近更新 更多