Search code examples
c++c++20concept

How to write concepts that make use of ADL


I would like to write a concept that would allow me to verify if a given statement, using ADL, is valid and has a proper return type.

In my specific case, I want to write a String concept that should enforce the following requirements:

  • The type has begin and end semantics for both its const and non-const flavors:

     // Akin to what this function does for `T` and `T const`
     template< typename T >
     auto test(T& t) {
         using std::begin;
         return begin(t);
     }
    
     // calling test with `T` and `T const` should be valid.
    
  • The return types of begin and end are consistent for both const and non-const flavors and they satisfy the std::contiguous_iterator concept.

So far I went with a trait implementation like the following:

namespace Adl {

using std::begin;

template< typename T >
using HasBeginT = decltype(begin(std::declval< T >()));

}

template< typename T >
using HasBegin = std::experimental::is_detected< Adl::HasBeginT, T >;

But I would like to directly embed this ADL usage in the definition of my constraint instead.


Solution

  • The idiom using std::X; X(...); is considered a bad idea post-C++20. The standard idiom now is to create a customization point object for X. Or in your case, use the existing customization point object: std::ranges::begin.

    The way you call such a customization point is by spelling it out in full; internally, it can make an ADL call (without using anything) if the type being provided has such a call.