TransWikia.com

Why does tag_invoke pattern need the Niebloid std::tag_invoke at all?

Stack Overflow Asked on December 20, 2020

This question assumes familiarity with the customization point management technique tag_invoke, introduced in P1895R0.

A customization point object can be defined according to P1895R0 as:

inline constexpr struct foo_cpo {
    // simplified original by omitting noexcept forward and using auto arg
    auto operator()(auto const &x) -> decltype( std::tag_invoke(*this, x) ) {
        return std::tag_invoke(*this, x); // <--^-- here are the Niebloid
    }
} foo;

But given the crux of this technique is to work with objects directly, and delegate any and all ADL to one and only agreed-upon identifier tag_invoke, then it seems the same effects can be achieved by simply,

inline constexpr struct {
    auto operator()(auto const &x) -> decltype( tag_invoke(*this, x) ) {
        return tag_invoke(*this, x); // no Niebloid. directly ADL call tag_invoke
    }
} foo;

For instance, the type erasure example from P1895R0, which is https://godbolt.org/z/3TvO4f, can be reimplemented without using the Niebloid at all: https://godbolt.org/z/dzqE7b. The code is the same as the original verbatim, modulo the definition of the Niebloid std::tag_invoke and using the above ADL form for all customization points objects.

What is the requirement that the presence of Niebloid really satisfies for tag_invoke?

One Answer

I don't think it's strictly necessary for tag_invoke itself to be a function object. But defining it as an object gives us a handy place to put a poison-pill overload should we decide that's necessary. And it's generally nice to have functions as first-class citizens that can be passed to higher-order functions. That's it, really.

Correct answer by Eric Niebler on December 20, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP