Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use C++20 concepts properly in a using declaration?

I was playing around a bit with Concepts offered in C++20 and came up with a simple example, which, to my surprise, does not produce the expected results (please leave any discussion on the usefulness of my example be :-)):

#include <iostream>
#include <type_traits>
#include <vector>

template <typename T>
concept i_am_integral = requires { std::is_integral_v<T> == true; };

template <typename T> requires i_am_integral<T>
using intvector = std::vector<T>;

int main() {
    intvector<int> v = { 1, 2, 3 }; // <- This is fine, int is an integral type

    // I would expect this to fail:
    intvector<double> w = { 1.1, 2.2, 3.3 };

    // I'm curious, so let's print the vector
    for (auto x : w) { std::cout << x << '\n'; }

    // Same here - IMO, this should fail:
    struct S{};
    intvector<S> s;
}

I tried to make intvector a "restricted" std::vector which is only allowed to take integral types. However, intvector seems to swallow arbitrary types just like the original vector, including user defined types.

Is this my fault or is clang not yet stable enough to handle this case properly? I suspect there is an issue in mixing type aliases and requirements (as stated in this answer), but I am unable to grasp it - in particular, my example compiles, while the one in the referenced post doesn't.

like image 484
andreee Avatar asked Mar 04 '23 06:03

andreee


1 Answers

Your concept:

template <typename T>
concept i_am_integral = requires { std::is_integral_v<T> == true; };

does not check if the type is integral. Instead, it checks if comparing std::is_integral_v<T> with true is possible (which is always possible). To fix your code you should just do:

template <typename T>
concept i_am_integral = std::is_integral_v<T>;
like image 96
bartop Avatar answered Mar 15 '23 19:03

bartop