如何定义一个满足任意 std::vector 的概念?
How can I define a concept that is satisfied by an arbitrary std::vector?
我想要一个 concept
需要一个任意向量作为 return 类型:
template<typename T>
concept HasVector = requires (T t) {
{ T.vec() } -> std::same_as<std::vector<int>>; //works
{ T.vec() } -> std::same_as<std::vector<foo>>; //want to put something arbitrary in here
}
这样我们就会有类似下面的东西:
class A {
std::vector<int> vec() { /* ... */}
}
class B {
std::vector<double> vec() { /* ... */}
}
static_assert(HasVector<A>);
static_assert(HasVector<B>);
此外,如果需要一个 vector 作为 return 类型,其值类型满足一些其他概念,即
会更好
template<typename T>
concept Arithmetic = // as in the standard
template<typename T>
concept HasArithmeticVector = requires (T t ) {
{ T. vec() } -> std::same_as<std::vector<Arithmetic>>;
有没有办法把这个放在概念的名字里?
只要vec()
是publicclass方法即可:
template<typename T> struct is_vector { std::false_type operator()(); };
template<typename T, typename A> struct is_vector<std::vector<T, A>> {
std::true_type operator()();
};
template<typename T>
concept HasVector = requires(T t) {
{ is_vector<decltype(t.vec())>{}() } -> std::same_as<std::true_type>;
};
class A {
public:
std::vector<int> vec() {return {}; }
};
class B {
public:
std::vector<double> vec() {return {}; }
};
class C {
};
static_assert(HasVector<A>);
static_assert(HasVector<B>);
我们首先编写一个变量模板来检查一个类型是否特化了一个模板:
template <typename T, template <typename...> class Z>
inline constexpr bool is_specialization_of = false;
template <template <typename...> class Z, class... Args>
inline constexpr bool is_specialization_of<Z<Args...>, Z> = true;
我们可以将其转化为一个概念:
template <typename T, template <typename...> class Z>
concept Specializes = is_specialization_of<T, Z>;
然后我们可以用它来实现另一个概念:
template<typename T>
concept HasVector = requires (T t) {
{ t.vec() } -> Specializes<std::vector>;
};
如果您想进一步检查,那只是增加了更多的要求。
template<typename T>
concept HasVector = requires (T t) {
{ t.vec() } -> Specializes<std::vector>;
// or something along these lines
requires Arithmetic<decay_t<decltype(t.vec()[0])>>;
requires Arithmetic<range_value_t<decltype(t.vec())>>;
// etc.
};
#include <concepts>
#include <vector>
template<typename T>
concept Arithmetic = std::integral<T> || std::floating_point<T>;
template<typename T>
concept HasVector = requires (T t) {
[]<Arithmetic U, typename A>(std::vector<U,A> const&){}(t.vec());
};
我想要一个 concept
需要一个任意向量作为 return 类型:
template<typename T>
concept HasVector = requires (T t) {
{ T.vec() } -> std::same_as<std::vector<int>>; //works
{ T.vec() } -> std::same_as<std::vector<foo>>; //want to put something arbitrary in here
}
这样我们就会有类似下面的东西:
class A {
std::vector<int> vec() { /* ... */}
}
class B {
std::vector<double> vec() { /* ... */}
}
static_assert(HasVector<A>);
static_assert(HasVector<B>);
此外,如果需要一个 vector 作为 return 类型,其值类型满足一些其他概念,即
会更好
template<typename T>
concept Arithmetic = // as in the standard
template<typename T>
concept HasArithmeticVector = requires (T t ) {
{ T. vec() } -> std::same_as<std::vector<Arithmetic>>;
有没有办法把这个放在概念的名字里?
只要vec()
是publicclass方法即可:
template<typename T> struct is_vector { std::false_type operator()(); };
template<typename T, typename A> struct is_vector<std::vector<T, A>> {
std::true_type operator()();
};
template<typename T>
concept HasVector = requires(T t) {
{ is_vector<decltype(t.vec())>{}() } -> std::same_as<std::true_type>;
};
class A {
public:
std::vector<int> vec() {return {}; }
};
class B {
public:
std::vector<double> vec() {return {}; }
};
class C {
};
static_assert(HasVector<A>);
static_assert(HasVector<B>);
我们首先编写一个变量模板来检查一个类型是否特化了一个模板:
template <typename T, template <typename...> class Z>
inline constexpr bool is_specialization_of = false;
template <template <typename...> class Z, class... Args>
inline constexpr bool is_specialization_of<Z<Args...>, Z> = true;
我们可以将其转化为一个概念:
template <typename T, template <typename...> class Z>
concept Specializes = is_specialization_of<T, Z>;
然后我们可以用它来实现另一个概念:
template<typename T>
concept HasVector = requires (T t) {
{ t.vec() } -> Specializes<std::vector>;
};
如果您想进一步检查,那只是增加了更多的要求。
template<typename T>
concept HasVector = requires (T t) {
{ t.vec() } -> Specializes<std::vector>;
// or something along these lines
requires Arithmetic<decay_t<decltype(t.vec()[0])>>;
requires Arithmetic<range_value_t<decltype(t.vec())>>;
// etc.
};
#include <concepts>
#include <vector>
template<typename T>
concept Arithmetic = std::integral<T> || std::floating_point<T>;
template<typename T>
concept HasVector = requires (T t) {
[]<Arithmetic U, typename A>(std::vector<U,A> const&){}(t.vec());
};