There is a template class A
with template parameter T
. I want this class to have a method f
if T
is of integral types. The class A
also has a lot of other methods, so I don't want to have specialization of overall A
.
I understand that this problem can be solved using inheritance, but my question is about concepts and requirements.
This code
template <typename T>
struct A {
void f();
};
template <>
void A<int>::f() {}
works as I expect. It makes implementation of f
for the int
type only. If I try to call A<std::string>{}.f();
it generates a linker error as expected.
But if I write
template <typename T>
struct A {
void f();
};
template <std::integral T>
void A<T>::f() {}
either
template <typename T> requires std::is_integral_v<T>
void A<T>::f() {}
the method f
is generated for all types, so calling A<std::string>{}.f();
does not give any error.
Also this works
template <typename T>
struct A {
void f() {}
};
template <>
void A<std::string>::f() = delete;
but this
template <typename T>
struct A {
void f() {}
};
template <std::integral T>
struct A<T>::f() = delete;
gives compilation error, namely redefinition of f
.
P.S. It seems such constructions are not allowed at all, but g++
just ignores concepts in definition of method f
.
There are four syntactical methods of applying constraints to a function.
template< Concept TypeID >
.template< class TypeID > requires constexpr-andor-requires-expression
.void f(Concept auto id);
.template< class TypeID > void f() requires constexpr-andor-requires-expression
.The function you want to constrain doesn't have a template parameter list so you can't use methods 1 and 2. Method 3 essentially generates template parameters. So that leaves method 4.