简体   繁体   中英

Explicit range-v3 decltype evaluates to 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() {
}

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++ version g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0)

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 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 
  • 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.

A working version would be:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM