Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the design reason template overloading of structs is not allowed in C++20?

In answer to my previous question I learned that C++ 20 concepts do not allow overloading on struct template arguments, for example this does not work:

#include <concepts>

template <std::integral>
struct S{

};
template <std::floating_point>
struct S{
};

For curious clang error is something like, but that does not matter since I know C++ standard does not allow this code to work:

type constraint differs in template redeclaration

I find this nonworking way of writing templates very natural so I wonder was this ever considered, and if so why it was rejected during standardization?

P.S. this seems to work in C++20, but I find it much uglier

#include <concepts>
#include <iostream>

template <typename T>
requires std::integral<T> || std::floating_point<T>
struct S{

};
template <std::integral T>
struct S<T>{
    static constexpr char msg[] = "i";

};
template <std::floating_point T>
struct S<T>{
    static constexpr char msg[] = "fp";
};

int main() {
    std::cout <<  S<char>::msg << std::endl;
    std::cout <<  S<double>::msg << std::endl;
}
like image 808
NoSenseEtAl Avatar asked Nov 01 '25 01:11

NoSenseEtAl


2 Answers

C++ has never had overloading for classes or class templates. Classes of course have no parameters with which an overload might be chosen, but neither can one write

template<class> struct A {};
template<int> struct A {};

even though for every template-id it is obvious which would pertain (A<int> vs. A<1>). There are several reasons for this restriction:

  1. It’s impossible to write generic code that uses one of the above overloads chosen at instantiation time: for every A<…>, whether the argument is a type or a value is fixed even if it’s dependent. (This wouldn’t be true if the overloads were template<int&> and template<float&>, of course.)
  2. Templates are occasionally mentioned without any template arguments, and there’s no syntax for selecting one where both might apply. One such context is as a template template argument (that might be of the generic template<class...> class variety); another is CTAD.
  3. Some ADL-like mechanisms would be necessary to support the case of overloading a class template for an application type after generic code that used the template(s).
  4. It would not in general be possible to determine to which overload a partial specialization pertained.

The C++20 behavior is just the continuation of this model; it’s not hard to add a generic

template<class> struct S;  // undefined

to serve as an umbrella over partial specializations declared as

template<std::integral I>
struct S<I> {};
template<std::floating_point F>
struct S<F> {};
like image 195
Davis Herring Avatar answered Nov 03 '25 16:11

Davis Herring


Template argument deduction does not work with an explicit specialization of a class template (in comparison to a function template). This has nothing to do with concepts per se. You will need the template<> keyword and the <T> parameter.

I do not know of and cannot find any standard proposal further shortening this.

In the following code especially the primary definition of S got much shorter than the working version in the question.

#include <concepts>

template <typename T>
concept Number = std::integral<T> || std::floating_point<T>;


template <Number T>
struct S;

template <std::integral T>
struct S<T>{
};

template <std::floating_point T>
struct S<T>{
};

The above code compiles and works.

By using Number the first line of the error message for instantiating S with e.g. std::string is:

error: template constraint failure for 'template<class T> requires Number<T> struct S'

Which is easy to understand and to the point (with more detailing information in the following lines about std::string not being an integral || floating_point). So it is possible to build levels of error messages for wrong instantiations (e.g. you could define your own integral concept which lists the allowed integer types).

like image 42
Sebastian Avatar answered Nov 03 '25 16:11

Sebastian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!