Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an out-of-class member template definition need a repetition of its declaration 'requires-clause'

This is related to the following question: Does a class template's requires clause have to be repeated outside member definitions?

In other words, given the code for the following templated struct A, the requires-clause needs to be repeated for the foo() function definition (per the standard paragraphs quoted in the linked question above)

template <typename T>
    requires std::integral<T> //'requires-clause'
struct A
{
    void foo();
};

template <typename T>
    requires std::integral<T> //This 'requires-clause' is required by the standard to be reiterated
void A<T>::foo()
{
    //
}

//Specialisations do not require explicit 'requires-clause'
template <>
void A<int>::foo()
{
    //
}

//Specialisation with a type that does not meet the constraint raises a compile-time error
template <>
void A<double>::foo() //Not allowed because std::integral(double) == false
{
    //
}

But I don't know why it is necessary to repeat the requires-clause for the specific class members described in [temp.class]\3. I can't think of a situation where this requirement would make a difference. In the example above, if the requires-clause is with the struct definition, any attempt to instantiate anything that isn't an integral type would not compile, so whether A<T>::foo() also requires that std::integral<T> == true is irrelevant. AFAIK it also makes no difference during specialisation because any attempt to specialise to a different type from an integral (as in this example) leads to an compilation error.

However, I'm sure that there are legitimate reasons for including this requirement in the standard - can anybody demonstrate a situation where the absence of this requires-clause on the definition would cause an issue?

like image 401
NotAProgrammer Avatar asked Dec 02 '20 10:12

NotAProgrammer


People also ask

How do you define a template function outside class?

It's quite common to separate a template into 2 files, one being a traditional header, and the second being the implementation, as with non-templated functions and their implementation. The only difference is that you need to #include the template implementation file as well as the header when you want to use it.

What is template What is the need of template declare a template class?

Templates in c++ is defined as a blueprint or formula for creating a generic class or a function. To simply put, you can create a single function or single class to work with different data types using templates. C++ template is also known as generic functions or classes which is a very powerful feature in C++.

What is class template What is the difference between class and class template?

An individual class defines how a group of objects can be constructed, while a class template defines how a group of classes can be generated. Note the distinction between the terms class template and template class: Class template. is a template used to generate template classes.

When class is there why do we need template?

What are Class Templates in C++? Templates are the mechanism by which C++ implements the generic concept. Simply, they allow you to pass data type as a parameter so that you don't need to write the same code for different data types.


1 Answers

According to the last section of https://en.cppreference.com/w/cpp/language/constraints you can specialize templates not only on parameters but also on their constraints. Like parameter specializations the standard defines also a partial ordering of constraints, such that a template specialization might be more constrained than another.

So, for example, you may have a more constrained specialization of your template A:

template <typename T>
    requires std::unsigned_integral<T>
struct A
{
    void foo();
};

With a different implementation of the element function foo:

template <typename T>
    requires std::unsigned_integral<T>
void A<T>::foo()
{
    // different implementation of foo() relying on T being unsigned integral
}

So, without the repeated requires clause in the definitions of both versions of A<T>::foo the compiler would not know to which specialization of A the defined foo would belong.

like image 143
bjhend Avatar answered Sep 20 '22 21:09

bjhend