问题
Let us consider following code:
#include <concepts>
template<typename X>
struct Concrete_M {
X f() const { return X{}; }
};
struct Concrete_X {};
template<typename T, typename X>
concept M = requires (T t)
{
{ t.f() } -> std::convertible_to<X>;
};
template<M<Concrete_X>>
struct C {};
const C<Concrete_M<Concrete_X>> c{};
Can I use following template template parameter T
?
template<template<typename> typename T, typename X>
concept M = requires (T<X> t)
{
{ t.f() } -> std::convertible_to<X>;
};
How should I change
template<M<Concrete_X>>
struct C {};
const C<Concrete_M<Concrete_X>> c{};
to properly use updated concept M
? I am looking for something like this:
template<typename X, /* ... */>
struct C {};
const C<Concrete_X, /* ... */> c{};
but I don't understand what should I put instead of /* ... */
comments. I tried:
template<typename X, M<X>>
struct C {};
const C<Concrete_X, Concrete_M<Concrete_X>> c{};
but GCC 10.0.1 raises an error:
(...) ‘M’ does not constrain a type (...)
回答1:
The shorter hand type-constraint syntax for concepts:
template <Concept T>
struct C { };
is only valid for those cases where Concept
's first template parameter is a type parameter. When that is not the case, you have to simply use the long form syntax: a requires-clause:
template <template <typename> class Z>
requires M<Z, Concrete_X>
struct C {};
The equivalent longer-form for my initial example is:
template <typename T> requires Concept<T>
struct C { };
The long form and short form mean the same thing - there's no functionality different here.
来源:https://stackoverflow.com/questions/62363891/can-concepts-be-used-with-template-template-parameters