- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在玩弄模板并尝试实现以下助手。
first_constructible<Types..., Args...>::type
这将返回第一种 Types
可从 Args...
构建.第一个问题显然是在 struct
中有两个参数包,所以我将用法更改为
first_constructible<std::tuple<Types...>, Args...>::type
我通过将元组类型拆分为 first 和 rest 来实现它,使用 std::is_constructible
检查并在必要时递归。
template<typename T>
struct pop_front_tuple
{
template<typename U, typename... Us>
static std::tuple<Us...> impl(std::tuple<U, Us...>);
using type = decltype(impl(std::declval<T>())); // std::tuple with removed first type
};
template<typename Tuple, typename... Args>
struct first_constructible
{
using first_type = decltype(std::get<0>(std::declval<Tuple>()));
using type = typename std::conditional
<
std::is_constructible<first_type, Args...>::value,
first_type,
typename first_constructible<typename pop_front_tuple<Tuple>::type, Args...>::type
>::type;
};
// end of recursion
template<typename... Args>
struct first_constructible<std::tuple<>, Args...>
{
using type = void;
};
但由于某种原因它不起作用。即
first_constructible<std::tuple<std::string, int>, std::string>::type a = ""; // works, a is std::string
first_constructible<std::tuple<std::string, int>>::type a = ""; // fails, error: variable or field 'a' declared void
first_constructible<std::tuple<std::string, int>, std::string::size_type, std::string::value_type> // fails, same error
我不知道我的错误在哪里。 std::is_constructible<std::string>::value
和 std::is_constructible<std::string, std::string::size_type, std::string::value_type>::value
是真的。
最佳答案
首先,一些元编程玩具:
template<class Tag>
using type_t = typename Tag::type;
template<class T> struct tag_t{using type=T; constexpr tag_t(){}};
template<class T> constexpr tag_t<T> tag{};
template<class...Tuples>
using cat_tuples = decltype(std::tuple_cat( std::declval<Tuples>()... ));
template<template<class...>class Z, class Tuple, class=void>
struct filter;
template<template<class...>class Z, class Tuple>
using filter_t = type_t<filter<Z,Tuple>>;
template<template<class...>class Z>
struct filter<Z, std::tuple<>,void>:tag_t<std::tuple<>>{};
template<template<class...>class Z, class T0, class...Ts>
struct filter<Z, std::tuple<T0, Ts...>, std::enable_if_t<Z<T0>::value>>:
tag_t<
cat_tuples<
std::tuple<T0>,
filter_t<Z, std::tuple<Ts...>>
>
>
{};
template<template<class...>class Z, class T0, class...Ts>
struct filter<Z, std::tuple<T0, Ts...>, std::enable_if_t<!Z<T0>::value>>:
filter<Z, std::tuple<Ts...>>
{};
现在我们解决您的问题:
template<class...Args>
struct is_constructible_test {
template<class T>
using result=std::is_constructible<T,Args...>;
};
template<class Tuple, class...Args>
using all_constructible_t = filter_t<is_constructible_test<Args...>::template result, Tuple>;
template<class Tuple, class...Args>
using first_constructible = std::tuple_element_t<0, all_constructible_t<Tuple,Args...>>;
测试代码:
struct bob {
bob( int, int, int ) {}
};
template<std::size_t>
struct alice {
alice(int) {}
};
int main() {
using is_alice = first_constructible<std::tuple<std::string, bob, alice<1>, alice<2>, int>, int>;
static_assert( std::is_same<is_alice, alice<1>>::value, "works" );
}
C++14,但仅适用于 _t
别名。替换 std::foo_t<blah>
与 typename std::foo<blah>::type
.
我所做的是找到每个 可构造类型,然后捕获第一个。过滤器是一个简单的概念,它比写“首先通过测试”更容易,因为过滤器后跟无条件首先获取在逻辑上是相同的(如果更昂贵的话)。
你可以修改filter
当测试通过时,上面“短路”并返回而不是与尾部连接:
template<template<class...>class Z, class Tuple, class=void>
struct search;
template<template<class...>class Z, class Tuple>
using search_t = type_t<search<Z,Tuple>>;
template<template<class...>class Z>
struct search<Z, std::tuple<>,void>{};
template<template<class...>class Z, class T0, class...Ts>
struct search<Z, std::tuple<T0, Ts...>, std::enable_if_t<Z<T0>::value>>:
tag_t<T0>
{};
template<template<class...>class Z, class T0, class...Ts>
struct search<Z, std::tuple<T0, Ts...>, std::enable_if_t<!Z<T0>::value>>:
search<Z, std::tuple<Ts...>>
{};
并替换 first_constructible
模板:
template<class Tuple, class...Args>
using first_constructible = search_t<is_constructible_test<Args...>::template result, Tuple>;
我可能会像您那样使用与元组交互而不是专门化的实用函数,这会有优势。
我看到你的一个问题是 get<>
返回一个引用,而不是一个值。 std::tuple_element_t
可能是更好的计划。
关于c++ - 查找类型,其中 is_constructible 成立,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43901862/
我在玩弄模板并尝试实现以下助手。 first_constructible::type 这将返回第一种 Types可从 Args... 构建.第一个问题显然是在 struct 中有两个参数包,所以我将用
我正在我的 Kotlin 项目中实现 RxJava。将从 Java 到 Kotlin 的自动翻译应用到以下代码: @Override protected void onCreate(Bundle sa
这个问题在这里已经有了答案: Comparing String to Integer gives strange results (5 个答案) 关闭 9 年前。 下面代码的输出是“失败”,但如果我
Deno & Node.js 作者 Ryan Dahl 和联合创始人 Bert Belder 宣布成立了 Deno 公司。 Ryan Dahl 和 Bert Belder 在博客中阐述
我最近参加了一个代码力量竞赛。在比赛的编辑部分,我看到了按位运算符之间的一种美妙关系,即 x + y = x & y + x |是的我还不知道证据。我拿了几个数字来看看这个等式是否正确。我很高兴知道这
我是一名优秀的程序员,十分优秀!