gpt4 book ai didi

c++ - 如何创建类型列表的笛卡尔积?

转载 作者:IT老高 更新时间:2023-10-28 23:11:38 25 4
gpt4 key购买 nike

我想使用可变参数模板创建类型列表的叉积。

这是我目前所拥有的:

#include <iostream>
#include <typeinfo>
#include <cxxabi.h>

template<typename...> struct type_list {};

template<typename T1, typename T2> struct type_pair {};

template<typename T, typename... Rest>
struct row
{
typedef type_list<type_pair<T,Rest>...> type;
};

template<typename... T>
struct cross_product
{
typedef type_list<typename row<T,T...>::type...> type;
};

int main()
{
int s;
typedef cross_product<int, float, short>::type result;
std::cout << abi::__cxa_demangle(typeid(result).name(), 0, 0, &s) << std::endl;

return 0;
}

这个程序输出:

$ g++ -std=c++0x cross_product.cpp ; ./a.out 
type_list<type_list<type_pair<int, int>, type_pair<int, float>, type_pair<int, short> >, type_list<type_pair<float, int>, type_pair<float, float>, type_pair<float, short> >, type_list<type_pair<short, int>, type_pair<short, float>, type_pair<short, short> > >

但我希望它输出:

type_list<type_pair<int,int>, type_pair<int,float>, type_pair<int,short>, type_pair<float,int>,...>

也就是说,没有嵌套的type_lists。

是否有没有 row 帮助器的直接方法,或者解决方案是否应该以某种方式“解包”嵌套的 type_list

最佳答案

我认为一个不错的干净版本:

cross_product.cpp:

#include "type_printer.hpp"

#include <iostream>

template<typename ...Ts> struct type_list {};
template<typename T1, typename T2> struct pair {};

// Concatenation
template <typename ... T> struct concat;
template <typename ... Ts, typename ... Us>
struct concat<type_list<Ts...>, type_list<Us...>>
{
typedef type_list<Ts..., Us...> type;
};

// Cross Product
template <typename T, typename U> struct cross_product;

// Partially specialise the empty case for the first type_list.
template <typename ...Us>
struct cross_product<type_list<>, type_list<Us...>> {
typedef type_list<> type;
};

// The general case for two type_lists. Process:
// 1. Expand out the head of the first type_list with the full second type_list.
// 2. Recurse the tail of the first type_list.
// 3. Concatenate the two type_lists.
template <typename T, typename ...Ts, typename ...Us>
struct cross_product<type_list<T, Ts...>, type_list<Us...>> {
typedef typename concat<
type_list<pair<T, Us>...>,
typename cross_product<type_list<Ts...>, type_list<Us...>>::type
>::type type;
};

struct A {};
struct B {};
struct C {};
struct D {};
struct E {};
struct F {};

template <typename T, typename U>
void test()
{
std::cout << print_type<T>() << " \u2a2f " << print_type<U>() << " = "
<< print_type<typename cross_product<T, U>::type>() << std::endl;
}

int main()
{
std::cout << "Cartesian product of type lists\n";
test<type_list<>, type_list<>>();
test<type_list<>, type_list<A>>();
test<type_list<>, type_list<A, B>>();
test<type_list<A, B>, type_list<>>();
test<type_list<A>, type_list<B>>();
test<type_list<A>, type_list<B, C, D>>();
test<type_list<A, B>, type_list<B, C, D>>();
test<type_list<A, B, C>, type_list<D>>();
test<type_list<A, B, C>, type_list<D, E, F>>();
return 0;
}

type_printer.hpp:

#ifndef TYPE_PRINTER_HPP
#define TYPE_PRINTER_HPP

#include "detail/type_printer_detail.hpp"

template <typename T>
std::string print_type()
{
return detail::type_printer<T>()();
}

#endif

detail/type_printer_detail.hpp:

#ifndef DETAIL__TYPE_PRINTER_DETAIL_HPP
#define DETAIL__TYPE_PRINTER_DETAIL_HPP

#include <typeinfo>
#include <cxxabi.h>
#include <string>

template <typename ...Ts> struct type_list;
template <typename T1, typename T2> struct pair;

namespace detail {

// print scalar types
template <typename T>
struct type_printer {
std::string operator()() const {
int s;
return abi::__cxa_demangle(typeid(T).name(), 0, 0, &s);
}
};

// print pair<T, U> types
template <typename T, typename U>
struct type_printer<pair<T, U>> {
std::string operator()() const {
return "(" + type_printer<T>()() + "," + type_printer<U>()() + ")";
}
};

// print type_list<T>
template <>
struct type_printer<type_list<>> {
std::string operator()() const {
return "\u2205";
}
};

template <typename T>
struct type_printer<type_list<T>> {
std::string operator()() const {
return "{" + type_printer<T>()() + "}";
}
std::string operator()(const std::string& sep) const {
return sep + type_printer<T>()();
}
};

template <typename T, typename ...Ts>
struct type_printer<type_list<T, Ts...>> {
std::string operator()() const {
return "{" + type_printer<T>()() + type_printer<type_list<Ts...>>()(std::string(", ")) + "}";
}
std::string operator()(const std::string& sep) const {
return sep + type_printer<T>()() + type_printer<type_list<Ts...>>()(sep);
}
};
}

#endif

运行:

g++ -std=c++0x cross_product.cpp && ./a.out

输出:

Cartesian product of type lists
∅ ⨯ ∅ = ∅
∅ ⨯ {A} = ∅
∅ ⨯ {A, B} = ∅
{A, B} ⨯ ∅ = ∅
{A} ⨯ {B} = {(A,B)}
{A} ⨯ {B, C, D} = {(A,B), (A,C), (A,D)}
{A, B} ⨯ {B, C, D} = {(A,B), (A,C), (A,D), (B,B), (B,C), (B,D)}
{A, B, C} ⨯ {D} = {(A,D), (B,D), (C,D)}
{A, B, C} ⨯ {D, E, F} = {(A,D), (A,E), (A,F), (B,D), (B,E), (B,F), (C,D), (C,E), (C,F)}

(我注意到在使用 Chrome 的 Windows 上,交叉乘积 unicode 字符无法正常显示。抱歉,我不知道如何解决。)

关于c++ - 如何创建类型列表的笛卡尔积?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9122028/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com