Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/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+编写和检查自己的概念+; 我正在编写一个只使用模板的头文件C++库。现在,我想添加一些概念检查,以处理在模板参数中使用不正确类型时引发的编译时错误_C++_Boost_Template Meta Programming_C++ Concepts - Fatal编程技术网

用c+编写和检查自己的概念+; 我正在编写一个只使用模板的头文件C++库。现在,我想添加一些概念检查,以处理在模板参数中使用不正确类型时引发的编译时错误

用c+编写和检查自己的概念+; 我正在编写一个只使用模板的头文件C++库。现在,我想添加一些概念检查,以处理在模板参数中使用不正确类型时引发的编译时错误,c++,boost,template-meta-programming,c++-concepts,C++,Boost,Template Meta Programming,C++ Concepts,例如,我需要能够指向单个对象的类指针对象(如std::shared_ptr)、能够指向数组(通过操作符[])但不能与指针算法一起使用的类指针对象(如std::unique_ptr)以及能够与指针算法一起使用的指针等概念 因为概念仍然不是标准的,编译器也不支持,所以我需要自己实现它。我知道Boost概念库,但出于某种原因,我不想将其添加到依赖项中 所以问题是,如何实现某些类型需求的检查?它是如何在Boost中实现的?在这种情况下,什么技术是常见的?自从我仍然使用C++11以来,我自己也做过一些类似

例如,我需要能够指向单个对象的类指针对象(如std::shared_ptr)、能够指向数组(通过操作符[])但不能与指针算法一起使用的类指针对象(如std::unique_ptr)以及能够与指针算法一起使用的指针等概念

因为概念仍然不是标准的,编译器也不支持,所以我需要自己实现它。我知道Boost概念库,但出于某种原因,我不想将其添加到依赖项中


所以问题是,如何实现某些类型需求的检查?它是如何在Boost中实现的?在这种情况下,什么技术是常见的?

自从我仍然使用C++11以来,我自己也做过一些类似的事情。基本上,这样做的方法是大量使用SFINAE并熟悉所有这些内容:

概念检查中最重要的是
enable\u if
:如果第一个模板参数为
true
,则该模板提供给定的返回类型,如果该参数为
false
,则会导致替换失败:

//this one gets called only for pointers
template <typename T>
typename enable_if<is_pointer<T>::value, bool>::type do_stuff(T) {}

//this one gets called only for non-pointers
template <typename T>
typename enable_if<not is_pointer<T>::value, bool>::type do_stuff(T) {}
现在,让我们来看看更难的部分:定义自己的概念,比如模板。如果可能的话,最好的方法就是根据上面链接中已经存在的标准编写它们。但是,有时您需要检查那里不可用的东西,例如,特定操作的可用性。在这种情况下,SFINAE是您的朋友:

template <typename T>
class is_equality_comparable {
    template <typename U> static auto check(const U& u) -> typename std::conditional<
            std::is_convertible<decltype(u == u), bool>::value,
            std::true_type, std::false_type>::type;
    static std::false_type check(...);
public:
    static constexpr bool value = decltype(check(std::declval<T>()))::value;
};
模板
阶级是平等的{
模板静态自动检查(常量U&U)->typename std::conditional<
std::是否可转换::值,
std::true\u type,std::false\u type>::type;
静态标准::假_类型检查(…);
公众:
静态constexpr bool value=decltype(检查(std::declval())::value;
};
这将检查特定类型是否定义了相等运算符(
operator==
),以及是否返回可以用作
bool
的内容。但是,它是如何实现的,需要做一些解释:这个类所做的主要工作是定义一个从未调用过的
check
方法,并通过计算
check
的返回类型来生成正确的值。在底部,该类只是这样做的:当使用类型为
T
的虚值调用时,它确定
check
的返回类型(通过
declval
生成,以避免依赖构造函数)。为了使其正常工作,提供了两个
check
重载:第一个重载是模板化的,第二个重载使用
..
符号,以接受任何参数,并具有比第一个重载更低的选择优先级。第一个重载使用一个后缀返回类型,这样它就可以引用它的参数(这使代码更干净),并根据
操作符==
是否正确返回可以用作
bool
的内容,使用
conditional
true\u类型
false\u类型
之间进行选择。如果
操作符==
不存在,第一个重载将导致替换失败,SFINAE将确保从可能的重载列表中悄悄地丢弃它,这意味着对
检查的假设调用将返回到第二个重载,该重载只返回
false\u type


当然,这只是我做这件事的方式;这是一种有效的方法,但我不确定Boost是这样做的,还是其他人是这样做的。如果你能够使用一个更新的C++版本,并支持实际的概念,那么你应该明确地使用它:在其他一些好的特性中,如果你做了错误的事情,你就可以得到可理解的错误信息,这不一定是你从上面提到的方法中得到的东西。最后,如果您真的决定做这样的事情,那么严格的测试是至关重要的:当您的类已经在代码中的其他地方使用时,很容易出错,并且很难找出如何修复它。

自从我仍然使用C++11以来,我自己也做了一些类似的事情。基本上,这样做的方法是大量使用SFINAE并熟悉所有这些内容:

概念检查中最重要的是
enable\u if
:如果第一个模板参数为
true
,则该模板提供给定的返回类型,如果该参数为
false
,则会导致替换失败:

//this one gets called only for pointers
template <typename T>
typename enable_if<is_pointer<T>::value, bool>::type do_stuff(T) {}

//this one gets called only for non-pointers
template <typename T>
typename enable_if<not is_pointer<T>::value, bool>::type do_stuff(T) {}
现在,让我们来看看更难的部分:定义自己的概念,比如模板。如果可能的话,最好的方法就是根据上面链接中已经存在的标准编写它们。但是,有时您需要检查那里不可用的东西,例如,特定操作的可用性。在这种情况下,SFINAE是您的朋友:

template <typename T>
class is_equality_comparable {
    template <typename U> static auto check(const U& u) -> typename std::conditional<
            std::is_convertible<decltype(u == u), bool>::value,
            std::true_type, std::false_type>::type;
    static std::false_type check(...);
public:
    static constexpr bool value = decltype(check(std::declval<T>()))::value;
};
模板
阶级是平等的{
模板静态自动检查(常量U&U)->typename std::conditional<
std::是否可转换::值,
std::true\u type,std::false\u type>::type;
静态标准::假_类型检查(…);
公众:
静态constexpr bool value=decltype(检查(std::declval())::value;
};
这将检查特定类型是否定义了相等运算符(
operator==
),以及是否返回可以用作
bool
的内容。然而,它是如何做到的,需要一些解释:这个类所做的主要事情是定义一个从未被调用的
check
方法,并通过计算
ch来生成正确的值