SD57
SD57

Reputation: 83

No type named 'type' in 'struct std::common_reference<Ref&&, const Val&>'

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 &>'

Upvotes: 0

Views: 839

Answers (1)

康桓瑋
康桓瑋

Reputation: 42776

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;
};

Demo.

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.

Upvotes: 0

Related Questions