I'm trying to write a proxy iterator using Boost.STLInterfaces. It fails to compile because the lvalue reference of the value and the rvalue reference of the reference are different, see a simplified version on Compiler Explorer https://godbolt.org/z/aE3bq7en4. How do I make two types have common reference? I tried overloading the addressof operator to return the reference type, but compiling a distilled example
#include <type_traits>
class Ref {};
class Val {};
// overload addressof operator
constexpr Ref operator&(Val) noexcept;
constexpr Ref operator&(Ref) noexcept;
int main()
{
std::common_reference<Ref&&, const Val&>::type t;
return 0;
}
fails with
error: no type named 'type' in 'std::common_reference<Ref &&, const Val &>'
In this case, you need to partial specialize std::basic_common_reference
to define the common reference of the two, similar to this:
template<template<class> class TQual, template<class> class UQual>
struct std::basic_common_reference<Ref, Val, TQual, UQual> {
using type = Val;
};
template<template<class> class TQual, template<class> class UQual>
struct std::basic_common_reference<Val, Ref, TQual, UQual> {
using type = Val;
};
Some issues worth noting:
Val
's member functions need to be public
.Val
's constructor should not be explicit
to satisfy indirectly_readable
.Val
's operator=(Ref ref)
needs to return Val&
to meet sortable
.Ref
needs to add operator=(Val) const
overload to satisfy indirectly_writable
.