有没有办法编写一种类型的"for-eachability"的 SFINAE 测试?
Is there a way to write a SFINAE test of "for-eachability" of a type?
我已经使用SFINAE表达式来测试一个类型是否支持operator<<
namespace details
{
template<typename T>
struct sfinae_true : std::true_type
{
};
template<typename T>
sfinae_true<decltype (std::declval<std::ostream &> () << std::declval<T const &> ())> test_for_ostream (int);
template<typename T>
std::false_type test_for_ostream (long);
}
template<typename T>
struct supports_ostream : decltype (details::test_for_ostream<T> (0))
{
};
我想测试的是,这一类型的T
是否可以像一样迭代
for (auto && v : vs) {} // vs is T const &
困境在于,这是一个语句,而不是一个使其与decltype
不兼容的表达式
我想用lambdas把一个语句转换成像这样的表达式
auto x = [] () { for (auto && v : vs) {}; return 0; } (); // vs is T const &
然而,包含lambda的decltype表达式似乎被明确禁止:
// Won't compile in clang, gcc nor VC++
using x_t = decltype ([] () { for (auto && v : vs) {}; return 0; } ()); // vs is T const &
因此,这使它无法在这样的测试功能中使用:
namespace details
{
template<typename T>
sfinae_true<decltype (
[] () { for (auto && v : std::declval<T const &> ()) ; } ()
)> test_for_container (int);
// Won't work because lambdas aren't allowed in unevaluated contexts
template<typename T>
std::false_type test_for_container (long);
}
template<typename T>
struct is_container : decltype (details::test_for_container<T> (0))
{
};
所以我已经没有什么想法了,所以我想也许有人@Stackoverflow可以想出一些有趣的东西。
PS。
我可以理解为什么decltype ([] () {})
是不允许的,但decltype ([] () {} ())
应该总是定义明确的,即void
。
在大多数情况下,以下特征就足够了:
#include <type_traits>
#include <utility>
#include <iterator>
namespace detail
{
using std::begin;
using std::end;
template <typename T>
auto is_range_based_iterable(...)
-> std::false_type;
template <typename T
, typename I = typename std::decay<decltype(std::declval<T>().begin())>::type>
auto is_range_based_iterable(int)
-> decltype(std::declval<T>().begin()
, std::declval<T>().end()
, ++std::declval<I&>()
, void()
, std::integral_constant<bool,
std::is_convertible<decltype(std::declval<I&>() != std::declval<I&>()), bool>::value
&& !std::is_void<decltype(*std::declval<I&>())>::value
&& std::is_copy_constructible<I>::value
>{});
template <typename T
, typename I = typename std::decay<decltype(begin(std::declval<T>()))>::type>
auto is_range_based_iterable(char)
-> decltype(begin(std::declval<T>())
, end(std::declval<T>())
, ++std::declval<I&>()
, void()
, std::integral_constant<bool,
std::is_convertible<decltype(std::declval<I&>() != std::declval<I&>()), bool>::value
&& !std::is_void<decltype(*std::declval<I&>())>::value
&& std::is_copy_constructible<I>::value
>{});
}
template <typename T>
struct is_range_based_iterable : decltype(detail::is_range_based_iterable<T>(0)) {};
测试:
#include <vector>
#include <array>
int main()
{
static_assert(is_range_based_iterable<std::vector<int>>::value, "!");
static_assert(is_range_based_iterable<std::array<int, 5>>::value, "!");
static_assert(is_range_based_iterable<int(&)[5]>::value, "!");
}
DEMO
相关文章:
- 为什么我的 for 循环给出错误:X 没有命名类型
- for 循环说 - 错误 成员引用基类型"int [13]"不是结构或联合
- 使用"JSON for Modern C++"库检测整数不适合指定类型?
- C++参数类型以接受适用于基于范围的 for 循环的所有序列
- 类型安全 - all_of/ any_of/ none_of for std::tuple
- 如何使用 Linux API for C 确定文件系统类型(名称)?
- C++函数模板:必须使用 & for 参数类型和返回类型?
- 对"vtable for "命名空间继承的未定义引用 对"类型信息"的未定义引用
- 什么C++类型用于最快的"for cycles"?
- 对于相互转换的类型,有没有办法绕过"deduced conflicting types for parameter in template instantiation"?
- 获取存储在 YAML::Node for yaml-cpp 中的值的类型
- 使用 decltype for 函数生成的非类型模板参数
- C++是否有以下类型的 for 循环或某种使用模板的方法
- 基于范围的 for 循环是否可以采用类型参数
- 在 for 循环中使用 int 以外的数据类型作为索引值C++
- 有没有办法编写一种类型的"for-eachability"的 SFINAE 测试?
- 我可以在for循环的初始化中声明不同类型的变量吗?
- 强制auto为range for循环中的引用类型
- for循环需要运行LLONG_MAX次数,但是计数器变量也需要表示有符号的数字.你用什么类型的柜台?
- 如何使我的自定义类型与"range-based for loops"一起使用?