Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ “如何表达表格的条件”;模板T是一个……”;使用概念?_C++_C++ Concepts_C++20 - Fatal编程技术网

C++ “如何表达表格的条件”;模板T是一个……”;使用概念?

C++ “如何表达表格的条件”;模板T是一个……”;使用概念?,c++,c++-concepts,c++20,C++,C++ Concepts,C++20,很容易表达“T型是E的容器”: 模板 概念bool is_container=requires(T,E){ {t.push_back(e)}->void; }; 模板需要is_容器 void moo() { T;E; t、 推回(e); } (检查的具体内容并不那么重要) 现在我需要表达这样一个条件:“对于任何类型的E,T是一个容器” 模板需要is\U容器 void moo() { T-ti; ti.推回(1); T-ts; t.推回(“abc”s); } 在这种情况下,如何编写is_con

很容易表达“T型是E的容器”:

模板
概念bool is_container=requires(T,E){
{t.push_back(e)}->void;
};
模板需要is_容器
void moo()
{
T;E;
t、 推回(e);
}
(检查的具体内容并不那么重要)

现在我需要表达这样一个条件:“对于任何类型的E,T是一个容器”

模板需要is\U容器
void moo()
{
T-ti;
ti.推回(1);
T-ts;
t.推回(“abc”s);
}

在这种情况下,如何编写
is_container

基本上,您所要求的内容不可能以您暗示的方式实现,但通过简单的解决方法,您可以实现相同的结果

要知道
T
是任何类型
E
的容器,编译器需要为每个可能的
E
实例化
T
,并对照条件进行检查,这是不可能的,因为有无限多的可能类型
T
(例如,想象链
T

您可以做的是从一个公共基类(标记)派生所有容器类(那些是任何
E
的容器)

struct container_tag{};
模板
类现有容器类:公共容器标记
{
公众:
使用值_type=E;
/* ... */
};
然后写一个这样的概念:

template<class T>
concept bool concept_container = std::is_base_of_v<container_tag, T>;
模板
concept bool concept_container=std::是_v的_base_;
然后像这样使用它:

template<concept_container T>
void moo() {
    T t;
    T::value_type e;
    t.push_back(e);
}
模板
void moo(){
T;
T::值_类型e;
t、 推回(e);
}

与中的许多不可能的事情一样,这相当于解决Halt

您有一个图灵完全语言(模板)中的任意函数,并希望确定函数的每个输出(模板的每个实例)是否满足某些属性

赖斯定理说这是不可能的

这是图灵完整元编程语言(如模板)的缺点之一

template <class T, class E>
concept bool is_container = requires(T t, E e) {
    { t.push_back(e) } -> void;
};

struct random {};

template <template<class> class T>
concept bool is_generic_container = is_container<T<random>, random>;
现在,您可以随身携带模板,并根据特定类型进行检查。但在一个足够复杂的程序中,这很像发明用来解决问题的问题概念;接口错误,而不是实现中的深层错误。

C++模板缺少。给定一个模板,只能检查其特定实例化的属性,而不能检查模板本身的属性(或者“所有实例化”)。不同的实例化可能具有不同的属性

因此,显然不可能编写像
的第二个变体is\u container
这样的概念

这里有一个非常简单的、黑客式的、局部的解决方法。其思想是,如果模板实例化并适用于某个随机类型,那么它也可能适用于其他类型。当然,不受控制的专业化和高级模板魔术将打破这一假设,但我们只是回到了常规未检查模板的起点

template <class T, class E>
concept bool is_container = requires(T t, E e) {
    { t.push_back(e) } -> void;
};

struct random {};

template <template<class> class T>
concept bool is_generic_container = is_container<T<random>, random>;
模板
概念bool is_container=requires(T,E){
{t.push_back(e)}->void;
};
结构随机{};
模板
概念bool是通用容器=是容器;

我们如何确保每个
C
都传递一个给定的概念(因为用户可以添加专门化)?在这里,您的代码只要求
T
T
是容器…@Jarod moo的代码只是一个例子,用户不知道也不感兴趣用什么特定类型实例化。@Jarod42“我们怎么能确定每个C都通过一个给定的概念“这是一个有趣的观点。一般来说,我们不知道会有哪些专业。因此,这看起来不太可能。也许通过内省,您可以循环检查
T
的所有专业,并为每个专业设置
require
。不幸的是,标记并非真正可行,因为我们希望能够对标准库组件和第三方组件进行概念检查。
template<concept_container T>
void moo() {
    T t;
    T::value_type e;
    t.push_back(e);
}
template <class T, class E>
concept bool is_container = requires(T t, E e) {
    { t.push_back(e) } -> void;
};

struct random {};

template <template<class> class T>
concept bool is_generic_container = is_container<T<random>, random>;