Apologies for potentially wrong title, that is my best guess what is happening.
I was learning some basic concepts and tried this:
#include <concepts>
#include <iostream>
#include <memory>
template<typename T>
concept eight = sizeof(T) == 8;
template<typename T>
concept basic = std::is_trivial_v<T>;
template<typename T>
requires eight<T>
constexpr void ff(){
std::cout << "eight" << std::endl;
}
template<typename T>
requires eight<T> && basic<T>
constexpr void ff(){
std::cout << "eight and basic" << std::endl;
}
template<typename T>
requires eight<T>
struct ffs{
};
template<typename T>
requires eight<T> && basic<T>
struct ffs{
};
What is insane to me is that I get error for struct when same stuff works for functions.
:29:10: error: requires clause differs in template redeclaration requires eight && basic ^ :24:10: note: previous template declaration is here requires eight
It could be that I am just UB NDRing in both cases but compiler does not mind in first case(not that when I remove structs from code my code seems to run as expected, including distinguishing properly what to invoke based on concepts), but that seems unlikely.
P.S. if somebody wonders why I just don't use requires instead of trivial concepts here is the answer.
CodePudding user response:
Overloading template classes wasn't allowed before concepts, and it still not allowed even with concepts. Use partial specialization:
template <typename T>
requires eight<T>
struct ffs {};
template <typename T>
requires basic<T>
struct ffs<T> {};
Or with the terse syntax:
template <eight T>
struct ffs {};
template <basic T>
struct ffs<T> {};
Note that in both cases, the constraints on the primary template automatically apply to all specializations.