Home > Back-end >  nested template struct in concept
nested template struct in concept

Time:06-14

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>>;
};

Demo

  • Related