The evaluation of 'requires expression' without usage of 'concept'

Viewed 127

Update: Jun 11th, 2022
Microsoft had fixed this since about 19.30 (kindly tested by user @Vuwox)

Link to the MSVC feedback:
https://developercommunity.visualstudio.com/t/The-evaluation-of-requires-expression/10059954

I am currently running into an issue that I am unsure whether it is a compiler error or not.
(The following test are running on https://godbolt.org/)
The code:

#include <iostream>
#include <tuple>
#include <typeinfo>

using namespace std;

struct A{};
struct B
{
    template<typename... Tys>
    bool IsPlayer() const noexcept
    {
        cout << "B::IsPlayer\nType count: " << sizeof...(Tys) << '\n';
        ((cout << typeid(Tys).name() << '\n'), ...);
        return sizeof...(Tys) > 1;
    }
};
struct C{};

template <typename... Tys>
struct Prefab_t
{
    using Tuple_t = std::tuple<Tys...>;
    Tuple_t m_tuple{};

    bool IsPlayer(void) const noexcept
    {
        auto fnHelper = [&]<typename T>(const T & Component) -> bool
        {
            //if constexpr (std::is_invocable_r_v<bool, decltype(&T::template IsPlayer<Tys...>), T const* const>)
            if constexpr (requires(const T& t) { {t.template IsPlayer<Tys...>()} noexcept -> std::same_as<bool>; })
            {
                cout << "fnHelper<"<<typeid(T).name() << ">\nType count: " << sizeof...(Tys) << '\n';
                ((cout << typeid(Tys).name() << '\n'), ...);
                return Component.template IsPlayer<Tys...>();
            }
            else if constexpr (requires(const T& t) { {t.IsPlayer()} noexcept -> std::same_as<bool>; })
                return Component.IsPlayer();
            else
                return false;
        };

        return (fnHelper(std::get<Tys>(m_tuple)) || ...);
    }
};

int main()
{
    Prefab_t<A, B, C> ent;
    cout << boolalpha << ent.IsPlayer();
    return 0;
}

With x86-64 gcc 12.1 and option -std=c++20, I got the wanted output:

fnHelper<1B>
Type count: 3
1A
1B
1C
B::IsPlayer
Type count: 3
1A
1B
1C
true

However, with compiler x64 msvc v19.latest and option /std:c++20, I got the unexpected output:

B::IsPlayer
Type count: 0
false

It seems like the lambda function fnHelper failed the if constexpr test and called the B::IsPlayer without any template argument.
Is my usage of requires expression correct? Is this way of use even legit?
Thank you.

PS please don't be harsh on me, I am just a chemical guy who has some interest in C++...

Edit:

  1. Shame on me, I even spelled "correct" wrongly to "current"...
  2. (June/01) Tested on Windows 11 with MSVC 2022 Community 17.3.0 Preview 1.1, exact same error. Triggered the contain of else if constexpr line via breakpoint debug.
0 Answers
Related