C++ Logo

sg10

Advanced search

Re: [SG10] [isocpp-core] Feature-test macro for ADL calls with template arguments?

From: Richard Smith <richardsmith_at_[hidden]>
Date: Mon, 8 Jun 2020 16:29:41 -0700
On Mon, Jun 8, 2020 at 2:18 PM Ville Voutilainen <
ville.voutilainen_at_[hidden]> wrote:

> On Tue, 9 Jun 2020 at 00:01, Richard Smith <richardsmith_at_[hidden]>
> wrote:
> > I thought the usual way you write ADL-only calls is
> >
> > template<typename T> void f(T t) {
> > using somewhere::name;
> > name(t); // ADL-only call with fallback to somewhere::name
> > }
>
> The "name" in this case is "get", and it needs to be called with a
> numeric template argument.
>
> > (eg, this is how I think we would recommend that people call 'begin' and
> 'end': "using std::begin; begin(x);"). I think that works equally well if
> 'somewhere' contains a function template, even if you don't have anything
> to put in namespace 'somewhere':
> >
> > namespace somewhere {
> > template<typename T> void name(...) = delete; // specialization missing
> > }
> > template<typename T> void f(T t) {
> > using somewhere::name;
> > name<int>(t); // ADL-only call with fallback to somewhere::name
> > }
> >
> > This works without a feature test macro, and is more reliable than
> relying on the new feature. (For example, the above pattern is not broken
> if someone incautiously adds a non-function, non-function-template 'name'
> to a scope enclosing 'f', whereas use of the new feature would be broken by
> that.)
>
> All we want is to be able to write QPair<What, Ever> qp; get<1>(qp);
>
> I don't know what that "somewhere" would be, nor do I know why I'd
> write a using-declaration for somewhere::get.
>

Consider:

// user.h
struct get {};

// user.cc
#include "user.h"
#include <QPair>

That won't compile with your above approach. Unqualified lookup for 'get'
finds the user's struct ::get, so ADL is not performed. Adding the
using-declaration fixes the problem:

// QPair
namespace detail {
  template<int> void get(...) = delete;
}
void whatever() {
  using detail::get; // add this to fix the problem
  QPair<What, Ever> qp;
  get<1>(qp); // ::get not found by unqualified lookup, so ADL is performed
now
}

If you have some default implementation of 'get' (such as a general
unspecialized one), then you could 'using' that instead of using a
placeholder one like detail::get.

Received on 2020-06-08 18:33:01