Search code examples
c++c++20c++-concepts

Is there any difference between `inline constexpr bool` and `concept`


template<typename T>
inline constexpr bool is_int_v1 = std::is_same_v<T, int>;

template<typename T>
concept is_int_v2 = std::is_same_v<T, int>;

In this code block whats the difference between the inline constexpr bool format and the concept format. Is one better over the other or are they equivalent?


Solution

  • There are many differences. Variables are variables; even if they are inline constexpr, they are still variables. They represent objects and you can take their addresses.

    A concept is not a variable at all. You cannot take its address or do anything of the kind with it. concepts get special grammatical rules like void func(ConceptName auto x); that variables do not.

    Variables can be templates and get to undergo template specialization. concepts don't get to be specialized; this is deliberate. A specific concept name is associated with exactly one constraint expression no matter what template arguments are given to it.

    But the most important difference is that concepts get to follow special subsumption rules during instantiation.

    When you attempt to instantiate a template that is constrained, C++ goes through a number of steps to determine which of the matching templates is the "most constrained" version that could be applied. The most constrained form is given greater weight during the resolution of which template to instantiate.

    std::signed_integral<T> is defined in terms of std::integral<T>.

    template<class T>
      concept signed_­integral = integral<T> && is_signed_v<T>;
    

    This means that, if some type T satisfies signed_integral, then it necessarily satisfies integral. If you have two versions of the same template, one constrained with integral and one with signed_integral, then passing unsigned int will necessarily instantiate the first.

    int satisfies both concepts. But since the compiler knows that signed_integral contains integral, it is considered "more constrained". And therefore, that template is given priority if a type fulfills both.

    That only happens if you use a concept. If these were just inline constexpr variables, then attempting to use int would get a compile error since both constraints are given equal weight.

    inline constexpr variables are essentially black boxes to the constraint system. concepts are part of the constraint system.