- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
假设我们有一个模板实例 Container<U, Args...>
(认为 Container
是一个 std::vector
)和一个非模板类型 T,我们需要检查我们是否可以调用 push_back
在 Container<T>
类型的对象上.下面是使用检测器习惯用法的代码:
#include <iostream>
#include <vector>
#include <set>
#include <string>
#include <type_traits>
#include <boost/iterator.hpp>
#include <boost/range.hpp>
template<typename, typename>
struct replace
{
using type = struct Error;
};
template<template<typename...> class Container, typename U, typename T>
struct replace<Container<U>, T>
{
using type = Container<T>;
};
template<typename Container, typename T>
using replace_t = typename replace<Container, T>::type;
template<typename Placeholder, template<typename...> class Op, typename... Args>
struct isDetected : std::false_type {};
template<template<typename...> class Op, typename... Args>
struct isDetected<std::void_t<Op<Args...>>, Op, Args...> : std::true_type {};
template<typename Container, typename T>
using pushBackDetector = decltype(std::declval<Container&>().push_back(std::declval<T>()));
template<typename Container, typename T>
bool canPushBack()
{
return isDetected<void, pushBackDetector, Container, T> {};
}
int main()
{
std::cout << canPushBack<replace_t<std::vector<int>, double>, double>() << std::endl;
std::cout << canPushBack<replace_t<std::set<int>, double>, double>() << std::endl;
std::cout << canPushBack<replace_t<boost::iterator_range<std::string::iterator>, std::string::iterator>, double>() << std::endl;
//std::cout << canPushBack<replace_t<boost::iterator_range<std::string::iterator>, int>, double>() << std::endl;
}
一个活生生的例子是 available在 Wandbox。
确实,它正确地推断出我们可以调用 push_back
在 std::vector<double>
, 但我们不能在 std::set<double>
上这样做或 boost::iterator_range<std::string::iterator>
.
现在让我们检查是否可以调用 push_back
在 boost::iterator_range<int>
并取消注释最后一行!现在代码爆炸得如此漂亮,我不会在这里给出完整的错误消息(最好在上面链接的实例中这样做),但它的要点是编译器试图实例化 boost::iterator_range<int>
并将无法实例化该类型的某些基本类型的失败转化为硬错误:
/opt/wandbox/boost-1.65.1/clang-5.0.0/include/boost/iterator/iterator_categories.hpp:119:60: error: no type named 'iterator_category' in 'std::__1::iterator_traits<int>'
typename boost::detail::iterator_traits<Iterator>::iterator_category
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
/opt/wandbox/boost-1.65.1/clang-5.0.0/include/boost/range/iterator_range_core.hpp:156:32: note: in instantiation of template class 'boost::iterators::iterator_traversal<int>' requested here
BOOST_DEDUCED_TYPENAME iterator_traversal<IteratorT>::type
^
/opt/wandbox/boost-1.65.1/clang-5.0.0/include/boost/range/iterator_range_core.hpp:436:67: note: in instantiation of template class 'boost::iterator_range_detail::pure_iterator_traversal<int>' requested here
BOOST_DEDUCED_TYPENAME iterator_range_detail::pure_iterator_traversal<IteratorT>::type
^
prog.cc:31:61: note: in instantiation of template class 'boost::iterator_range<int>' requested here
using pushBackDetector = decltype(std::declval<Container&>().push_back(std::declval<T>()));
^
prog.cc:28:31: note: in instantiation of template type alias 'pushBackDetector' requested here
struct isDetected<std::void_t<Op<Args...>>, Op, Args...> : std::true_type {};
^
prog.cc:36:12: note: during template argument deduction for class template partial specialization 'isDetected<std::void_t<Op<Args...> >, Op, Args...>' [with Op = pushBackDetector, Args = <boost::iterator_range<int>, double>]
return isDetected<void, pushBackDetector, Container, T> {};
^
一方面,这是完全有道理的——事实上,int
不是迭代器。另一方面,捕获这个不正确的实例化并返回 false
是非常可取的。来自 canPushBack()
在这种情况下。那么,问题来了:有没有可能把这个硬错误变成软错误并优雅地处理?
最佳答案
不,您不能采用不支持 SFINAE 检测的模板,并且在没有特定于所讨论类型的手动工作的情况下使其对 SFINAE 友好,有时这还不够。
你能做的最好的事情就是编写一个手动特征来为你完成它,以及一个 SFINAE 检查它是否可以应用的别名,并且只在可以的情况下返回一个类型。
此外,无法检测某物是否为迭代器。没有标准强制的 SFINAE 友好的“X 是一个迭代器”测试。作为一般规则,所有迭代器都必须支持 std::iterator_traits<T>
,但是当您将非迭代器传递给 std::iterator_traits
时,零 要求非迭代器必须生成 SFINAE 友好结果,根据我的经验,通过 void*
至 std::iterator_traits
生成非 SFINAE 友好结果。
您可以尝试破解一个 - 检测迭代器必须做的各种事情(可取消引用、可递增、同等可比较),但即使有一个类型在您尝试时也可能没有 SFINAE 友好的错误。例如,将非相等可比较类型放入 std::vector
中,并试图做 ==
可能会因硬错误而无法编译(至少我上次检查时是这样)。
一个简单的例子是:
template<class T>
struct problem {
static_assert(!std::is_same<T,int>{}, "oh oh");
};
通过 int
至 problem
不能被 SFINAE 检测为问题。如果实例化 problem<int>
,你会遇到一个硬错误。
关于c++ - 将 SFINAE 上下文中不正确的模板实例化的硬错误转变为软错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47352859/
算力时代,视频云需要怎样的 CPU? 在数据爆发式增长及算法日益精进的大背景下,属于「算力」的时代俨然到来。随着视频成为互联网流量的主角,日趋饱和的音视频场景渗透率、人类对“感官之限”的追
我正在使用 keras 开发深度网络。有一个激活“硬 sigmoid”。它的数学定义是什么? 我知道什么是 Sigmoid。有人在Quora上问了类似的问题:https://www.quora.com
我有一个不寻常的 SQL 问题,我不太确定如何最好地解释,所以请耐心等待。我有三张表,一张是志愿者组织的表,一张是用户的表,一张是用户详细信息的表。 #Table 1# ## Name Preside
我正在尝试使用名为 bigText 的 jquery 插件。一个很棒的用于创建 block 头的插件。如果您想将其与自定义字体一起使用,它会声明您需要 google webfont loader,这样
假设我有一张 table date,personid 1/1/2001 1 1/2/2001 3 1/3/2001 2 1/4/2001 2 1/5/2001 5 1/6/2001 5 1/7/200
下面是我要执行的 SQL。我想避免为此执行多个请求,我很确定这是可能的…… First table : products_categories (category_id, category_infos
我在 android studio 中重新设置了一些提交,并选择了硬重置类型。我失去了一个星期的工作。是否有希望撤销此操作?我正在使用 android studio,它有内置的 GUI 选项来执行所有
当我使用我的交叉工具链编译 C 代码时,链接器会打印出警告页面,说明我的可执行文件使用了硬 float ,但我的 libc 使用了软 float 。有什么区别? 最佳答案 硬浮点使用片上浮点单元。软
linux系统有arm64,arm架构armv8-a。如何知道 debian 是运行硬浮点还是软浮点? 最佳答案 符合 AAPCS64, GNU GCC for armv8 仅提供硬浮点 aarch6
我正在开发 cortex-m3 的微内核。我创建了一个故意导致错误的小型测试应用程序。 现在我不确定如何从故障中返回。我知道堆栈可能需要使用不同函数的地址进行更新。我也知道在某些情况下从错误返回可能是
硬/软 限制是什么意思? 核心文件大小的差异例如: ulimit -Sc 1024 与 ulimit -Hc 1024 我通常在运行二进制文件之前将脚本放入 ulimit -c unlimited。
我想在 Java 中加载一个 MSCAPI keystore 并检查 MY 存储中的可用证书。但是,这些证书的一些 key 驻留在硬件 token 上,并且弹出窗口会在加载期间询问 token 。 有
是的,这是一个有点棘手的问题; 一个数组(没有副本),而不是任何奇数数组。让我解释一下,让我们从这里开始; $a = array ( 'one' => 1, 'two' => 2, 'three' =
我需要在运行 Ubuntu 12.04 的 BeagleBoard xM rev C 上运行一个使用 ftd2xx 的程序。我正在尝试使用提供的 ARM 库 libftd2xx.so here . l
我是一名优秀的程序员,十分优秀!