Явный диапазон-v3 decltype оценивает как недействительный?
Я пытаюсь получить явный тип диапазона (я могу захотеть сохранить его как поле в классе в будущем). Однако, по некоторым причинам, он оценивает 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 это дает
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)
Я получаю сообщение об ошибке аналогичного типа в Visual Studio 2017, v. 15.9
Этот вопрос является продолжением моего другого вопроса: как сохранить диапазон как поле в классе? но более конкретно, и я считаю, что это заслуживает отдельного отношения.
1 ответ
Ваш код не работает, потому что:
Представление range / v3 отключает представление из rvalue, потому что это приведет к зависанию ссылки. Таким образом, в вашем
declval()
Вы также должны использовать lvalue:std::declval<std::set<Alpha*>&>() // ^ here should be lvalue
информация о трансформации вида кодируется внутри параметра шаблона. Так что если вы используете
view::transform(std::function<Beta*(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(std::function<Beta*(Alpha*)>{
[](Alpha* a) { return static_cast<Beta*>(a); }
});
}
Но на самом деле, хранить представление таким образом не очень хорошая идея.