简体   繁体   中英

Validity of C++20 concept

I am learning about C++20 concepts and I came across the following example that I don't know if it is well-formed(according to the standard) or not. The program is accepted by all compilers: Demo .

Basically, I want to know if this is the correct usage of concepts.

//define Element so that you can use it in vector require clause
template<typename T> bool constexpr Element(){
    if constexpr(std::is_same_v<T, int>)
    {
        return true;
    }
    else 
    {
        return false;
    }
};

template<typename T>        // for all types T
    requires (Element<T>())   // such that T is an Element
class vector {
        //...
};
int main()
{
    vector<int> v;
    
}

My question is that is this well-formed or is it ill-formed NDR. If there is anything wrong then how can we correct it here.

There is no "C++ concept" in this code, as evidenced by the lack of the use of the concept keyword. You are using a template definition constrained by a requires clause, but that requires clause doesn't use an actual concept .

As for the validity of the code, it is legal C++. Though it's also really bad C++. Your use of if constexpr over-complicates what could just be return std::is_same_v<T, int>; . Which means that your Element function could be an Element concept rather than a function call: template<typename T> concept Element = std::is_same_v<T, int>; . And since C++20 has the std::same_as concept, you don't even need that . You should always use a standard library concept if one will fit.

Yes, but no, It is well-formed because you are using type traits, which are compile-time boolean values. which are interchangeable with actual concepts and can be part of concept definitions.

At the same time, real concepts support a richer definition and usage syntax than booleans. For example, they can appear in template and function argument lists. Something like the following, although still a bit contrived, would make more sense to me:

#include <concepts>

template<std::integral T>
T constexpr foo_it(T value)
{
    if constexpr(std::same_as<T, int>) {
        // Do something specific for int values
    } else {
        // Generic function body for other integers
    }
    return value;
}

template<std::integral T> 
class vector {
        //...
};

int main()
{
    vector<int> v; // OK
    vector<double> w; // error: double is not integral
}

Your vector class example is odd in the sense that, if you were to design a vector only for integers, it would not need to be a template.

Apart from the usual learning materials, I've found it quite helpful to listen to Bjarne Stroustrup himself on this topic. Here is a short excerpt where he explains it to an interviewer.

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