c++ - 一个自包含的 C++ 概念可以匹配一个带有任何参数的特定模板吗?
问题描述
无论模板参数之一如何,我都想要一个匹配特定模板类型的 C++ 概念。当然,我可以使用其他一些辅助声明来区分模板类型。但是特别是概念和需求表达式的好处之一是它们消除了对辅助类型的许多需求。所以我想知道是否有可能通过一个概念声明来做到这一点“一体化”。
这是一个最小的工作示例:
#include <algorithm>
#include <compare>
#include <iostream>
#include <memory>
#include <string>
template<typename A> using char_string =
std::basic_string<char, std::char_traits<char>, A>;
using std::string;
template<typename T> struct AltAllocator : std::allocator<T> {};
using AltString = char_string<AltAllocator<char>>;
template<typename T> constexpr bool is_char_string_v = false;
template<typename A> constexpr bool is_char_string_v<char_string<A>> = true;
template<typename T> concept is_char_string = is_char_string_v<T>;
inline bool
operator==(is_char_string auto const &a, is_char_string auto const &b)
{
return std::equal(a.begin(), a.end(), b.begin(), b.end());
}
int
main()
{
string s;
AltString as;
std::cout << std::boolalpha << (s == as) << std::endl;
}
我希望能够在is_char_string
无需介绍的情况下进行定义is_char_string_v
。在这种特殊情况下,知道字符串包含它们的分配器类型,我当然可以用这样的东西“作弊”:
template<typename T> concept is_char_string =
std::same_as<T, char_string<typename T::allocator_type>>;
有没有更通用的方法来编写一个独立的概念来匹配使用任何模板参数实例化的某些特定模板?
解决方案
我不知道更广泛的问题可能是什么,但我们可以将检查某物是否为 a 的问题分解basic_string<char, char_traits<char>, A>
为以下问题:(1) 它是 abasic_string
和 (2) 它的前两种类型是char
and char_traits<char>
。
第一个问题是标准is_specialization_of
特征:
template <typename T, template <typename...> class Z>
inline constexpr bool is_specialization_of = false;
template <typename... Args, template <typename...> class Z>
inline constexpr bool is_specialization_of<Z<Args...>, Z> = true;
第二个我们可以使用Boost.Mp11进行一般类型列表操作。所以要么:
template <typename T>
concept char_string = is_specialization_of<T, std::basic_string>
&& std::same_as<mp_first<T>, char>
&& std::same_as<mp_second<T>, std::char_traits<char>>;
或者将后两者一起检查:
template <typename T>
concept char_string = is_specialization_of<T, std::basic_string>
&& std::same_as<
mp_take_c<T, 2>
std::basic_string<char, std::char_traits<char>
>;
在这里只取前两个参数是安全的,因为第三个是默认的。并且由于第二个也是默认设置,因此您可以改为比较 tostd::string
而不是std::basic_string<char, std::char_traits<char>
.
如果意图真的是避免任何依赖关系或任何其他类型,那么我想你可以这样写:
template <typename T>
concept char_string = requires (T t) {
[]<typename A>(std::basic_string<char, std::char_traits<char>, A>){}(t);
};
但我不确定这是个好主意。
推荐阅读
- java - 检查环境变量是否设置了运行时spring boot
- javascript - 从其他域加载 jquery
- c++ - 按位 AND 不起作用并禁止进一步访问变量(虽然它在观察者中工作)
- kubernetes - 重用依赖服务的就绪探测来控制服务的启动
- python - Series 的真值是模棱两可的
- c - 如何检查文件是否存在于C中的给定路径中?
- google-sheets-query - 使用包含来引用单元格值的查询导致解析错误
- http - 为什么 HTTP 标准在每条消息的开头没有“消息大小”?
- ios - UIButton 和 UILabel 在较小的屏幕上不可点击
- r - 选择符合条件的行和下一行