我最近开始学习 C++20 中引入的新特性。我在实现概念时遇到了一些麻烦。
玩具示例:
我想定义一个表示可调整大小数组的概念:
template<class T>
concept ResizableArray= std::is_same<std::vector<double>, T>::value;
这样的代码在 Visual Studio 下编译并且运行良好。但是,我一直在写一个表示任何大小的固定大小数组的概念(std::arraytemplate<template<unsigned int> class T, unsigned int S>
concept FixedArray = std::is_same<std::array<double, S>, T<double, S>>::value;
不编译!问题:
template<template<unsigned int> class T, unsigned int S>
concept Array= std::is_same<std::vector<double>, T>::value || std::is_same<std::array<double, S>, T<S>>::value;
不编译!任何建议,将不胜感激。
最佳答案
我认为您以错误的方式处理概念。如果您想要某些类型的强类型标志,模板类特化或常量表达式别名会像过去一样做得很好:
template<class A>
struct is_fixed_array : std::false_type {};
// only works with arrays by specialization.
template<class T, std::size_t I>
struct is_fixed_array<std::array<T,I>> : std::true_type {};
template<class T>
constexpr bool is_fixed_array_v = is_fixed_array<T>::value;
相反,使用概念,您希望检查对象接口(interface),而不管您拥有的实际类型如何,并避免像使用 std::is_same<>
那样进行强比较。 .这里有一个小例子说明我的意思:template<class T>
concept ResizableArray = requires(T container)
{
// I only accept types that have a method resize(std::size_t)
container.resize(std::size_t{0});
// further things that tells you is an array...
};
template<class T>
concept FixedArray = requires(T container)
{
// I only accept types that are specialized with tuple_size
std::tuple_size_v<T> -> std::convertible_to<std::size_t>;
// further things that tells you is an array...
};
// class with exactly the same interface as array
template<class T, std::size_t I>
struct MyArray : std::array<T,I> {};
static_assert(is_fixed_array_v<std::array<int,1>>);
// static_assert(is_fixed_array_v<MyArray<int,1>>); // assertion fails!
// instead, concepts work with any type that fullfil the defined interface
static_assert(ResizableArray<std::vector<int>>);
static_assert(not ResizableArray<MyArray<int,1>>);
static_assert(not FixedArray<std::vector<int>>);
static_assert(FixedArray<MyArray<int,1>>);
关于C++20 概念和模板 : fixe-size and resizable array,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62940931/