C++参数包类型扩展



我在c++中玩参数包,下面是我想要实现的:

我有这3个结构:

struct Base {
Base(int x) : x(41) {}
int x;
};
struct A : Base {
A() : Base(41) {}
};
struct B : Base {
B() : Base(42) {}
};

我想创建一个泛型函数,它返回一个元组,其中包含指定类型的实例,即

magicFunction<A,B,A,B,A> == std::tuple{A(), B(), A(), B(), A()} 
magicFunction<A,B,A> == std::tuple{A(), B(), A()} 

我试图使用模板专业化来扩展类型,但不幸的是无法做到(我理解它为什么不编译,只是不知道如何修复它:(


template<typename isEmpty, typename ...T>
struct ExpanderImpl {
};
template<typename Head, typename ... Rest>
struct ExpanderImpl<std::false_type, Head, Rest...> {
static std::tuple<Head, Rest...> getValues() {
if(sizeof...(Rest) > 0) {
return std::tuple_cat(std::tuple{Head()}, ExpanderImpl<std::false_type, Rest...>::getValues());
} else {
return std::tuple_cat(std::tuple{Head()}, ExpanderImpl<std::true_type, Rest...>::getValues());
}
}
};
template<typename ...Empty>
struct ExpanderImpl<std::true_type, Empty...> {
static std::tuple<Empty...> getValues() {
return {};
}
};
template<typename ...T>
struct Expander {
static std::tuple<T...> getValues() {
if(sizeof...(T) > 0) {
return ExpanderImpl<std::false_type, T...>::getValues();
} else {
return ExpanderImpl<std::true_type, T...>::getValues();
}
}
};

关于如何修复它,有什么建议吗?还有,有没有更好的方法来实现我想要的?

完整的代码可以在这里找到。谢谢你的帮助。

您想要的是

template <typename... T> std::tuple<T...> magicFunction() 
{
return {};
}

你会称之为

magicFunction<A,B,A,B,A>();

并且它将返回一个CCD_ 1。它的工作方式是return {};说返回一个初始化的值(T()/T{}(返回值,返回值是std::tuple<T...>,它是所有模板参数的元组

您似乎在寻找

template <typename... T>
using magicFunction = std::tuple<T...>;
int main() {
magicFunction<A,B,A>();
// If no default constructors supplied.
magicFunction<Base,Base,Base>(41, 42, 41); 
}
  • 尽管有更简单的方法来创建元组,但您的方法失败了,因为两个分支都应该用常规if实例化。

    if constexpr(C++17(解决了这个Demo。

    请注意,std::tuple{Head()}也是C++17构造。

    C++11将是CCD_ 9或CCD_。

  • 将实现保持在C++11中的方法是去掉这个运行时std::tuple<A,B,A,B,A>1,并使用std::conditional使用std::true_type/std::false_type

    template<typename Head, typename ... Rest>
    struct ExpanderImpl<std::false_type, Head, Rest...> {
    static std::tuple<Head, Rest...> getValues() {
    return std::tuple_cat(
    std::make_tuple(Head()),
    ExpanderImpl<typename std::conditional<(sizeof...(Rest) == 0),
    std::true_type,
    std::false_type>::type,
    Rest...>::getValues());
    }
    };
    template<typename ...T>
    struct Expander {
    static std::tuple<T...> getValues() {
    return ExpanderImpl<typename std::conditional<(sizeof...(T) == 0),
    std::true_type,
    std::false_type>::type,
    T...>::getValues();
    }
    };
    

    演示。

  • 你可以通过不同的专业化来摆脱is_empty

    template<typename ...Ts> struct Expander;
    // Non empty case
    template<typename Head, typename ... Rest>
    struct Expander<Head, Rest...> {
    static std::tuple<Head, Rest...> getValues() {
    return std::tuple_cat(
    std::make_tuple(Head()),
    Expander<Rest...>::getValues());
    }
    };
    // Empty case
    template<>
    struct Expander<> {
    static std::tuple<> getValues() { return {}; }
    };
    

    演示。

最新更新