Can concepts be used with template template parameters?

你。 提交于 2020-06-25 05:26:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!