显式范围-v3十进制类型评估为无效? [英] Explicit range-v3 decltype evaluates to void?

查看:98
本文介绍了显式范围-v3十进制类型评估为无效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获取范围的显式类型(将来我可能希望将其存储为类中的字段).但是,由于某种原因,它的值为void?

I am trying to get an explicit type of a range (I may want to store it as a field in a class in the future). However, for some reason, it evaluates to void?

#include <iostream>
#include <set>
#include <range/v3/view/transform.hpp>

class Alpha {
public:
  int x;
};

class Beta : public Alpha {

};

class Foo {
public:
  std::set<Alpha*> s;

  using RangeReturn = decltype(std::declval<std::set<Alpha*>>() | ranges::v3::view::transform(std::function<Beta*(Alpha*)>()));
  RangeReturn r();
};

Foo::RangeReturn Foo::r() {
  return s | ranges::v3::view::transform([](Alpha* a) { return static_cast<Beta*>(a); });
}

int main() {
}

使用g ++ -std = c ++ 17进行编译时,它会给出

When compiling with g++ -std=c++17, it gives

main.cpp:24:88: error: return-statement with a value, in function returning 'void' [-fpermissive]

(g ++版本g ++(Ubuntu 7.3.0-27ubuntu1〜18.04)7.3.0)

(g++ version g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0)

我在Visual Studio 2017 15.9版中收到类似错误

I get an error of similar kind on Visual Studio 2017, v. 15.9

这个问题是我其他问题的延续:

This question is a continuation of my other question: How to store a range as a field in a class? but is more specific and I believe it deserves to be separate.

推荐答案

您的代码不起作用,原因是:

Your code doesn't work because:

  • range/v3视图从右值禁用视图,因为这将导致悬空引用.因此,在您的declval()中,您还应该使用左值:

  • range/v3 view disables view from rvalue, because that will cause dangling reference. Thus in your declval(), you should also use an lvalue:

std::declval<std::set<Alpha*>&>()
//                           ^ here should be lvalue

  • 视图转换信息被编码在template参数内.因此,如果使用view::transform(std::function<Beta*(Alpha*)>())表示类型,则表达式应具有完全相同的类型. Lambda不好.

  • view transformation information is encoded inside the template parameter. So if you use view::transform(std::function<Beta*(Alpha*)>()) to represent the type, your expression should have exactly the same type. A lambda is not ok.

    有效版本为:

    class Foo {
    public:
      std::set<Alpha*> s;
    
      using RangeReturn = decltype(std::declval<std::set<Alpha*>&>() | ranges::v3::view::transform(std::function<Beta*(Alpha*)>()));
      RangeReturn r();
    };
    
    Foo::RangeReturn Foo::r() {
      return s | ranges::v3::view::transform(std::function<Beta*(Alpha*)>{
              [](Alpha* a) { return static_cast<Beta*>(a); }
              });
    }
    

    但是实际上,以这种方式存储视图不是一个好主意.

    But actually, it's not a good idea to store a view this way.

    这篇关于显式范围-v3十进制类型评估为无效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆