创建一个模板函数,该函数根据模板参数类型的条件返回不同的元组类型

oleksijp

首先,是否有可能根据某些条件返回不同的类型?其次,是否有一种更简洁的方式来处理这种映射,而无需枚举所有可能的if和else?

这里有很多(很多)的if,and和but

基本上,我想定义一个不完整的元组,我希望将其自动扩展以完成某些默认类型。当然,完整性与某些上下文有关。在此,B0和B1将是默认值。并且完整的元组必须具有形式<B0 or its derived, B1 or its derived>实际上,我工作中的元组具有两个以上的元素。

struct B0 { };
struct B1 { };

// here, a complete tuple is a tuple that has two elements: 
// of B0 type or its derived as a 1st element and
// of B1 type or its derived as a 2nd element

// templ argumets can be in the order B0, B1 or its derived or absent
template<class Tuple>
CompleteTuple make_complete_tuple()
{
    if (std::tuple_size<Tuple>::value == 0)
        return std::tuple<B0,B1>{};

    else if (std::tuple_size<Tuple>::value == 1)
    {
        using ElemT = std::tuple_element<0, Tuple>::type;

        if (std::is_base_of<B0, ElemT>::value)
            return std::tuple<ElemT, B1>{};
        if (std::is_base_of<B1, ElemT>::value)
            return std::tuple<B0, ElemT>{};
    }

    else if (std::tuple_size<Tuple>::value == 2)
    {
        using Elem0T = std::tuple_element<0, Tuple>::type;
        using Elem1T = std::tuple_element<1, Tuple>::type;

        if (std::is_base_of<B0, Elem0T>::value)
            if(std::is_base_of<B1, Elem1T>::value)
                return std::tuple<Elem0T, Elem1T>{};

        // not handling another conditions, the example is only for conveying idea
    }
}

struct A : public B0 { };
struct C : public B1 { };

int main()
{
    auto complete_tuple0 = make_complete_tuple<std::tuple<A>>();
    // complete_tuple0 shoud be std::tuple<A, B1>;

    auto complete_tuple1 = make_complete_tuple<std::tuple<C>>();
    // complete_tuple1 shoud be std::tuple<B0, C>;

    // etc

    std::cin.get();
    return 0;
}
昆比

C ++ 17解决方案,如果用替换_v usingsC ++ 11 ::value不需要不同的基数,但是它将始终用传递的元组参数中最左边的匹配类型替换默认元组中的每个默认基数。

#include <tuple>
#include <type_traits>


// Returns the first type from Ts that is derived from Base. Returns Base if there is not one.
template<typename Base,typename...Ts>
struct pick_derived;

// No Ts were derived from Base.
template<typename Base>
struct pick_derived<Base>{
    using type=Base;
};

template<typename Base,typename Derived, typename...Tail>
struct pick_derived<Base,Derived,Tail...>{
    using type = typename std::conditional<std::is_base_of_v<Base,Derived>,
                                           Derived,// Return it. Otherwise continue searching.
                                           typename pick_derived<Base,Tail...>::type>::type;
};

template<typename SourceTuple, typename DefaultTuple>
struct tup_transformer_impl;

template<typename...Ts, typename...Ds>
struct tup_transformer_impl<std::tuple<Ts...>,std::tuple<Ds...>>{
    // Fancy double pack expansion
    // For each default Ds type, try to replace it with a derived type from Ts.
    using type = std::tuple<typename pick_derived<Ds,Ts...>::type...>;
};


#include <iostream>   

struct B0 { };
struct B1 { };

// Tweak this.
using default_tuple = std::tuple<B0,B1>;
template<typename Tuple>
using tup_transform = typename tup_transformer_impl<Tuple,default_tuple>::type;


template<class Tuple>
tup_transform<Tuple> make_complete_tuple()
{
    return {};
}

struct A : public B0 { };
struct C : public B1 { };

 
int main()
{
    auto complete_tuple0 = make_complete_tuple<std::tuple<A>>();
    // complete_tuple0 shoud be std::tuple<A, B1>;
    static_assert(std::is_same_v<decltype(complete_tuple0),std::tuple<A, B1>>);

    auto complete_tuple1 = make_complete_tuple<std::tuple<C>>();
    // complete_tuple1 shoud be std::tuple<B0, C>;
    static_assert(std::is_same_v<decltype(complete_tuple1),std::tuple<B0, C>>);

    std::cin.get();
    return 0;
}

我猜你可以这样称呼它:

tup_transform<std::tuple<A>> complete_tuple0;

(将其更改tup_transform<A> complete_tuple0;为非常容易。只需将tup_transformer_impl更改为Ds...直接使用即可,而不是解压缩它们。)

当然,所有这些都要求每种类型都是默认可构造的。如果不是这种情况,我认为如果派生类型至少是可移动的,则该解决方案可以适用。在这种情况下,每个派生值都必须传递给make_complete_tuple函数。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

C ++模板函数根据模板参数返回类型

如何声明一个泛型函数,该函数返回一个具有相同参数但其参数返回类型不同的函数(反应钩子)

为函数创建模板函数,该函数接受函数指针作为许多类型的函数的参数

根据C ++模板函数的参数类型解析为不同的类型

创建一个C ++模板函数,该函数将返回特定大小的std :: array

在函数模板中,如何根据另一个参数确定一个参数的类型

如何创建一个名为 isNumber 的函数,该函数接收名为 val 的参数并返回一个布尔值,指示参数是否为 number 类型

从函数返回类型推断模板参数类型

如何根据模板类型参数调用不同的函数?

根据条件从功能模板返回不同的类型

具有不同模板参数的函数返回类型

如何使函数接受字符串参数,并根据该函数返回不同的结构类型?

让函数返回模板类型

是否可以在Haskell中创建一个函数,该函数返回数据类型的构造函数列表?

使用函数的返回类型作为另一个模板函数的调用

模板参数类的函数调用的返回类型

创建一个函数,该函数接受来自输入文本框的参数并在 javascript 中返回值的类型

我如何制作一个模板化函数,该函数采用的参数是boost :: bind的结果?

传递一个接受任意数量和类型参数的函数作为类模板参数

使用函数定义特征,该函数返回与一个参数具有相同生存期的关联类型

使用函数的返回类型和参数类型作为模板类型

UML类图:如果该函数返回一个函数调用,该函数的返回类型将如何处理?

Typescript返回一个函数,该函数返回具有类型约束的组件

函数模板中返回类型的模板参数推导

模板化函数模板参数的返回类型

检查模板参数类型是否被另一个函数接受的static_assert

如何将函数传递给模板化函数A,该函数可能基于A的另一个参数而具有不同的签名?

具有先前模板参数类型的自动返回类型参数的函数类型的模板参数

如何使用指定的向量类型创建一个接受值向量的模板函数?