简体   繁体   中英

Is there a 'requires' replacement for 'void_t'?

void_t is a nice hack to detect compilability of certain expressions, but I wonder if there is some way to do that check with requires (or requires requires ) since I really do not like void_t from the readability perspective.

For example, for a certain type I want to check if some expression is fine (ie compilable) or not, including negations.

Ideally I would wish that this works, but it does not, probably since lambdas are not templated...

#include <unordered_set>


int main() {
    auto a = []() requires requires(int x) {x<x;} {};
    auto b = []() requires !requires(std::unordered_set<int> x) {x<x;} {};
}

If this use seems weird, my real motivation is to check that something does not compile, for example that my nontemplated type does not have operator< or that it is not constructible from int or...

PS: I know boost::hana has a way to do this , I am looking for vanilla C++20 solution.

my real motivation is to check that something does not compile, for example that my nontemplated type does not have operator <

This is possible with concepts, perhaps I am misunderstanding?

template<class T>
concept has_less_than = requires(const T& x, const T& y)
{
   {x < y} -> std::same_as<bool>;
};

struct Has_Less
{
    bool operator<(const Has_Less& other) const
    {
        return true;
    }
};

struct Nope{};

int main()
{
    static_assert(has_less_than<Has_Less>);
    static_assert(!has_less_than<Nope>);
}

Live Demo

While the answer of @AndyG is perfectly fine, I would like to make an addition. You can make an ad-hoc concept as well, like you can see in the next example program (includes are missing):

void func( auto v )
{
    // unnamed concept in constexpr if-branch!
    if constexpr( requires { { v < v }->std::same_as<bool>; } ) {
        // use operator
        puts( "HAVE operator <" );
    } else {
        // cannot use operator
        puts( "no operator <" );
    }
}

struct X {};

int main()
{
    func( 2 );
    func( X{} );
    return EXIT_SUCCESS;
}

Tested with VisualStudio 2022 (17.3.5) in C++20 mode.

This technique is named "Design by introspection". I also recently wrote a short blog post to this (can be found in my profile).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM