В этом блоге post я видел, как Эрик Ниблер объяснял свое мнение о проверке концепции. Это выглядело как хороший баланс между простотой и практичностью для меня, поэтому я хотел попробовать.
Чтобы проверить себя, я придумал быструю концепцию векторных пространств. Вот код:
#include <range/v3/utility/concepts.hpp>
#include <array>
#include <algorithm>
#include <string>
struct vector_space
{
// Valid expressions
template<typename Field, typename Vector>
auto requires(Field &&f, Vector &&v1, Vector &&v2) -> decltype(
ranges::concepts::valid_expr(
f * v1,
v1 + v2
));
};
template<typename Field, typename Vector>
constexpr bool VectorSpace()
{
return ranges::concepts::models<vector_space, Field, Vector>();
}
template<typename Field, typename Vector,
CONCEPT_REQUIRES_(VectorSpace<Field, Vector>())>
void linear_comb(Field f1, Vector v1, Field f2, Vector v2)
{
return (f1 * v1) + (f2 * v2);
}
template <typename T, std::size_t dim>
std::array<T, dim> operator+(std::array<T, dim> const& a1,
std::array<T, dim> const& a2) {
std::array<T, dim> res;
std::transform(a1.begin(), a1.end(), a2.begin(),
res.begin(),
[](T const& e1, T const& e2) {
return e1 + e2;
});
return res;
}
template <typename Field, typename T, std::size_t dim>
std::array<T, dim> operator*(std::array<T, dim> const& a,
Field f) {
std::array<T, dim> res;
std::transform(a.begin(), a.end(),
res.begin(),
[f](T const& e) {
return f * e;
});
return res;
}
template <typename Field, typename T, std::size_t dim>
std::array<T, dim> operator*(Field f, std::array<T, dim> const& a) {
return a * f;
}
int main() {
std::string s1 = "hello";
std::string s2 = "world";
std::array<float, 4> a1{1.1f, 2.2f, 3.3f, 4.4f};
std::array<float, 4> a2{4.4f, 3.3f, 2.2f, 1.1f};
std::array<float, 4> a3 = (3.14f * a1) + (2.71f * a2);
linear_comb(3.14f, a1, 2.71f, a2);
}
Как видите, я хочу проверить, что значения v1, v2
из Vector
и f
из Field
, выражения f * v1
и v1 + v2
имеют смысл. Короче говоря, я хочу скалярное умножение и сложение векторов. Хотя я могу правильно вычислить a3
в main
, функция linear_comb
говорит мне, что концепция VectorSpace<Field, Vector>
не выполняется. Он правильно выводит Field
как float
и Vector
как std::array<float, 4>
. Почему тогда оно не рассматривается как правильное выражение?