Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MSVC Bug? Overloaded member not found for constrained function

This code fails to compile using MSVC 19.27.29112.0, but works with GCC 10.2.0. C++20 is enabled in both cases:

template <typename T>
struct Blah {
    void blah() requires (sizeof(T) == 4);
};

template <typename T>
void Blah<T>::blah() requires (sizeof(T) == 4) {}

int main() {
    Blah<int> b;
    b.blah();

    return 0;
}

error C2511: 'void Blah::blah(void)': overloaded member function not found in 'Blah'

The error only occurs if the requires depends on the class's template type. For example, requires (sizeof(int) == 4) works fine. Converting blah() to a templated function and doing something like requires (sizeof(U) == 4) also works.

Can anyone confirm this is a compiler bug?

like image 744
Daskie Avatar asked Oct 24 '20 22:10

Daskie


2 Answers

(Too long for a comment.)    This looks like a bug, indeed, and I suggest you formally report it.

Curiously enough, the following works, instead.

template <typename T>
struct Blah {
    enum { sizeofT = sizeof(T) };  // or: static const size_t sizeofT = sizeof(T);
                                   // or: static constexpr size_t sizeofT = sizeof(T);
    void blah() requires (sizeofT == 4);
};

template <typename T>
void Blah<T>::blah() requires (sizeofT == 4) {}

int main() {
    Blah<int>().blah();       // ok
    Blah<float>().blah();     // ok

//  Blah<short>().blah()      // c7500: 'blah': no function satisfied its constraints
//  Blah<double>().blah();    // c7500: 'blah': no function satisfied its constraints

    return 0;
}
like image 152
dxiv Avatar answered Oct 05 '22 05:10

dxiv


Apparently, gcc and clang knows the existent overload in your code (here). However, I think the MS compiler team would have pipelined the memory initialization module at a different stage as compared to gcc and clang. I (kind-of) speculate this since the following code works (i.e., initialize and create memory for the blah() function in the struct template itself):

template<typename T>
struct Blah {
    void blah() requires (sizeof(T) == 4) {};
};

int main() {
    Blah<int> b;
    b.blah();
}
like image 26
Jerry Ajay Avatar answered Oct 05 '22 05:10

Jerry Ajay