I have struct like that :
struct i32 {
template<int32_t x>
struct val {
static constexpr int32_t v = x;
};
template<typename v1, typename v2>
struct add {
using type = val<v1::v v2::v>;
};
template<typename v1, typename v2>
using add_t = typename add<v1, v2>::type;
};
Obviouly, I have many more methods and nested types in that struct. And I have also other similar structs, such as i64
and so on, which I name "Rings".
Later in the code, I have a template struct,
template<typename Ring>
struct FractionField {
// many things here
};
I'd like to have a c concept for my Ring type, so I can check at compile type that user defined "Rings" have the appropriate nested types and operations.
My attempt look like that :
template<typename T>
concept RingConcept = requires {
typename T::val; // how to express that val must be a template on a numeric value ??
typename T::template add_t<typename T::val, typename T::val>; // same here ??
};
However, none of my attempts have been conclusive.
Basically, I always get that kind of errors, without knowing how to fix them :
error: constraints not satisfied for alias template 'FractionField' [with Ring = i32]
using Q32 = FractionField<i32>;
note: because 'typename T::template add_t<typename T::val, typename T::val>' would be invalid: typename specifier refers to class template member in 'i32'; argument deduction not allowed here
typename T::template add_t<typename T::val, typename T::val>;
I hope I don't need to write a concept for every numeric types used for the nested template val
.
CodePudding user response:
The typename
in the requires
-clause is followed by a type rather than a template. Since T::val
is a class template that accepts a numeric value, simply instantiating T::val
with 0
should be enough
template<typename T, typename val = typename T::template val<0>>
concept RingConcept = requires {
typename T::template add_t<val, val>;
};
Or
template<typename T>
concept RingConcept = requires {
typename T::template val<0>;
typename T::template add_t<typename T::template val<0>,
typename T::template val<0>>;
};