The following code does not compile.
#include <iostream>
#include <memory>
#include <ranges>
#include <vector>
class Base
{
public:
virtual ~Base() = default;
virtual auto say() const -> void = 0;
};
class Derived : public Base
{
public:
auto say() const -> void override
{
std::cout << "Hi!\n";
}
};
auto say_all(std::ranges::view auto bases) -> void
{
for (auto const & base : bases)
{
base.say();
}
}
int main()
{
std::vector<std::unique_ptr<Derived>> bases;
bases.push_back(std::make_unique<Derived>());
bases.push_back(std::make_unique<Derived>());
say_all(bases | std::views::transform([](auto const & up) { return static_cast<Base &>(*(up.get())); }));
}
The error under gcc is quite lengthy:
<source>: In instantiation of 'main()::<lambda(const auto:11&)> [with auto:11 = std::unique_ptr<Derived>]':
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/type_traits:3302:30: required from 'struct std::is_invocable<main()::<lambda(const auto:11&)>&, std::unique_ptr<Derived, std::default_delete<Derived> >&>'
3302 | : public __bool_constant<__is_invocable(_Fn, _ArgTypes...)>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/type_traits:3707:71: required from 'constexpr const bool std::is_invocable_v<main()::<lambda(const auto:11&)>&, std::unique_ptr<Derived, std::default_delete<Derived> >&>'
3707 | inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
| ^~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/concepts:362:25: required by substitution of 'template<class _Vp, class _Fp> requires (input_range<_Vp>) && (copy_constructible<_Fp>) && ((view<_Vp>) && (is_object_v<_Fp>) && (regular_invocable<_Fp&, decltype(*(declval<decltype(std::ranges::__access::__begin((declval<_Container&>)()))&>)())>) && (__can_reference<typename std::invoke_result<_Fp&, decltype(*(declval<decltype(std::ranges::__access::__begin((declval<_Container&>)()))&>)())>::type>)) class std::ranges::transform_view [with _Vp = std::ranges::ref_view<std::vector<std::unique_ptr<Derived> > >; _Fp = main()::<lambda(const auto:11&)>]'
362 | concept invocable = is_invocable_v<_Fn, _Args...>;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges:2244:5: required by substitution of 'template<class _Range, class _Fp> std::ranges::transform_view(_Range&&, _Fp) -> transform_view<views::all_t<_Range>, _Fp> [with _Range = std::vector<std::unique_ptr<Derived> >&; _Fp = main()::<lambda(const auto:11&)>]'
2244 | transform_view(_Range&&, _Fp) -> transform_view<views::all_t<_Range>, _Fp>;
| ^~~~~~~~~~~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges:933:44: recursively required by substitution of 'template<class _Range> requires __adaptor_invocable<_Adaptor, _Range, const _Arg&> constexpr auto std::ranges::views::__adaptor::_Partial<std::ranges::views::_Transform, main()::<lambda(const auto:11&)> >::operator()(_Range&&) const [with _Range = std::vector<std::unique_ptr<Derived> >&]'
933 | = requires { std::declval<_Adaptor>()(declval<_Args>()...); };
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges:933:44: required by substitution of 'template<class _Self, class _Range> requires (__is_range_adaptor_closure<_Self>) && (__adaptor_invocable<_Self, _Range>) constexpr auto std::ranges::views::__adaptor::operator|(_Range&&, _Self&&) [with _Self = std::ranges::views::__adaptor::_Partial<std::ranges::views::_Transform, main()::<lambda(const auto:11&)> >; _Range = std::vector<std::unique_ptr<Derived> >&]'
<source>:37:107: required from here
37 | say_all(bases | std::views::transform([](auto const & up) { return static_cast<Base &>(*(up.get())); }));
| ^
<source>:37:72: error: cannot allocate an object of abstract type 'Base'
37 | say_all(bases | std::views::transform([](auto const & up) { return static_cast<Base &>(*(up.get())); }));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:7:7: note: because the following virtual functions are pure within 'Base':
7 | class Base
| ^~~~
<source>:11:22: note: 'virtual void Base::say() const'
11 | virtual auto say() const -> void = 0;
| ^~~
<source>: In function 'int main()':
<source>:37:19: error: no match for 'operator|' (operand types are 'std::vector<std::unique_ptr<Derived> >' and 'std::ranges::views::__adaptor::_Partial<std::ranges::views::_Transform, main()::<lambda(const auto:11&)> >')
37 | say_all(bases | std::views::transform([](auto const & up) { return static_cast<Base &>(*(up.get())); }));
| ~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| | std::ranges::views::__adaptor::_Partial<std::ranges::views::_Transform, main()::<lambda(const auto:11&)> >
| std::vector<std::unique_ptr<Derived> >
<source>:37:19: note: there are 7 candidates
37 | say_all(bases | std::views::transform([](auto const & up) { return static_cast<Base &>(*(up.get())); }));
| ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from <source>:3:
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges:981:5: note: candidate 1: 'template<class _Lhs, class _Rhs> requires (__is_range_adaptor_closure<_Lhs>) && (__is_range_adaptor_closure<_Rhs>) constexpr auto std::ranges::views::__adaptor::operator|(_Lhs&&, _Rhs&&)'
981 | operator|(_Lhs&& __lhs, _Rhs&& __rhs)
| ^~~~~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges:981:5: note: template argument deduction/substitution failed:
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges:981:5: note: constraints not satisfied
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges: In substitution of 'template<class _Lhs, class _Rhs> requires (__is_range_adaptor_closure<_Lhs>) && (__is_range_adaptor_closure<_Rhs>) constexpr auto std::ranges::views::__adaptor::operator|(_Lhs&&, _Rhs&&) [with _Lhs = std::vector<std::unique_ptr<Derived> >&; _Rhs = std::ranges::views::__adaptor::_Partial<std::ranges::views::_Transform, main()::<lambda(const auto:11&)> >]':
<source>:37:107: required from here
37 | say_all(bases | std::views::transform([](auto const & up) { return static_cast<Base &>(*(up.get())); }));
| ^
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges:962:13: required for the satisfaction of '__is_range_adaptor_closure<_Lhs>' [with _Lhs = std::vector<std::unique_ptr<Derived, std::default_delete<Derived> >, std::allocator<std::unique_ptr<Derived, std::default_delete<Derived> > > >&]
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges:963:9: in requirements with '_Tp __t' [with _Tp = std::vector<std::unique_ptr<Derived, std::default_delete<Derived> >, std::allocator<std::unique_ptr<Derived, std::default_delete<Derived> > > >&]
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges:963:70: note: the required expression 'std::ranges::views::__adaptor::__is_range_adaptor_closure_fn(__t, __t)' is invalid
963 | = requires (_Tp __t) { __adaptor::__is_range_adaptor_closure_fn(__t, __t); };
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
cc1plus: note: set '-fconcepts-diagnostics-depth=' to at least 2 for more detail
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges:972:5: note: candidate 2: 'template<class _Self, class _Range> requires (__is_range_adaptor_closure<_Self>) && (__adaptor_invocable<_Self, _Range>) constexpr auto std::ranges::views::__adaptor::operator|(_Range&&, _Self&&)'
972 | operator|(_Range&& __r, _Self&& __self)
| ^~~~~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ranges:972:5: note: substitution of deduced template arguments resulted in errors seen above
In file included from /cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/memory_resource.h:40,
from /cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/string:72,
from /cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/locale_classes.h:42,
from /cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/ios_base.h:43,
from /cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ios:46,
from /cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/ostream.h:43,
from /cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/ostream:42,
from /cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/iostream:43,
from <source>:1:
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/cstddef:141:3: note: candidate 3: 'constexpr std::byte std::operator|(byte, byte)'
141 | operator|(byte __l, byte __r) noexcept
| ^~~~~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/cstddef:141:18: note: no known conversion for argument 1 from 'std::vector<std::unique_ptr<Derived> >' to 'std::byte'
141 | operator|(byte __l, byte __r) noexcept
| ~~~~~^~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/ios_base.h:91:3: note: candidate 4: 'constexpr std::_Ios_Fmtflags std::operator|(_Ios_Fmtflags, _Ios_Fmtflags)'
91 | operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b) _GLIBCXX_NOTHROW
| ^~~~~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/ios_base.h:91:27: note: no known conversion for argument 1 from 'std::vector<std::unique_ptr<Derived> >' to 'std::_Ios_Fmtflags'
91 | operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b) _GLIBCXX_NOTHROW
| ~~~~~~~~~~~~~~^~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/ios_base.h:150:3: note: candidate 5: 'constexpr std::_Ios_Openmode std::operator|(_Ios_Openmode, _Ios_Openmode)'
150 | operator|(_Ios_Openmode __a, _Ios_Openmode __b) _GLIBCXX_NOTHROW
| ^~~~~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/ios_base.h:150:27: note: no known conversion for argument 1 from 'std::vector<std::unique_ptr<Derived> >' to 'std::_Ios_Openmode'
150 | operator|(_Ios_Openmode __a, _Ios_Openmode __b) _GLIBCXX_NOTHROW
| ~~~~~~~~~~~~~~^~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/ios_base.h:197:3: note: candidate 6: 'constexpr std::_Ios_Iostate std::operator|(_Ios_Iostate, _Ios_Iostate)'
197 | operator|(_Ios_Iostate __a, _Ios_Iostate __b) _GLIBCXX_NOTHROW
| ^~~~~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/ios_base.h:197:26: note: no known conversion for argument 1 from 'std::vector<std::unique_ptr<Derived> >' to 'std::_Ios_Iostate'
197 | operator|(_Ios_Iostate __a, _Ios_Iostate __b) _GLIBCXX_NOTHROW
| ~~~~~~~~~~~~~^~~
In file included from /cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/shared_ptr_atomic.h:33,
from /cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/memory:83,
from <source>:2:
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/atomic_base.h:104:3: note: candidate 7: 'constexpr std::memory_order std::operator|(memory_order, __memory_order_modifier)'
104 | operator|(memory_order __m, __memory_order_modifier __mod) noexcept
| ^~~~~~~~
/cefs/22/22e6cdc013c8541ce3d1548e_consolidated/compilers_c++_x86_gcc_15.2.0/include/c++/15.2.0/bits/atomic_base.h:104:26: note: no known conversion for argument 1 from 'std::vector<std::unique_ptr<Derived> >' to 'std::memory_order'
104 | operator|(memory_order __m, __memory_order_modifier __mod) noexcept
| ~~~~~~~~~~~~~^~~
Compiler returned: 1
Basically, it complains it cannot create an object of type Base as it is an abstract class. But why does it try to?
All I am trying to do is to create a view of references to base class and pass it to a function. The code here may not make much sense, but it is distilled from a larger example that uses multiple inheritance and just serves the purpose of illustrating the problem.