我正在尝试编写一个元函数(在haskell中)看起来大致如下:
gather :: [a] -> [a] -> ([a], [a])
gather (x:xs) (_:_:ys) = <something using x, xs, and ys>
...other pattern matches...
我能够使用roll-my-own自己的可变参数模板序列,但似乎无法弄清楚如何使用mpl执行此操作。
为简单起见,我正在尝试这个示例函数(应该帮助我理解我需要的东西):
//get_first :: [a] -> a
template<class SEQ_C>
get_first {
enum { value = -1 };
typedef get_first<SEQ_C> type;
};
//get_first (x:xs) = x
template<template<class T, T... S> class SEQ_C, class T, T x, T... xs>
struct get_first<SEQ_C<T, x, xs...>> {
enum { value = x };
typedef get_first<SEQ_C<T, x, xs...>> type;
};
...
typedef boost::mpl::vector_c<int 1, 2, 3> listA;
typedef get_first<listA>::type first;
std::cout << first::value << std::endl;
输出-1。
我已经尝试了许多不同的方式来获得比赛,我只是在黑暗中刺伤。文档似乎mpl::vector_c<int, x>
实际上是integral_c<int, x>
的列表 - 但尝试使用此结果是其他错误。
可能是模式匹配
答案 0 :(得分:2)
typedef get_first<SEQ_C> type;
行,则可以看到它):
error: ‘type’ in ‘struct get_first<boost::mpl::vector_c<int, 1l, 2l, 3l> >’ does not name a type
// ^ ^ ^
如您所见,g++
将传递的参数解释为long
,而不是int
。因此,如果您将规范更改为:
template<template<class T, long... S> class SEQ_C, class T, long x, long... xs>
struct get_first<SEQ_C<T, x, xs...>> {
enum { value = x };
typedef get_first<SEQ_C<T, x, xs...>> type;
};
它会起作用。
当然,这不是一个解决方案,我只是展示,它是如何工作的。我认为,这是g ++中的错误,因为clang ++会为你的代码生成1
。
答案 1 :(得分:1)
因此,在给予帮助的情况下,我能够提出似乎有用的东西。它需要一个long用于char,short,int,long类型的特化,以及用于long long的原始模板。
所以最终模板看起来像这样:
// get_first :: [a] -> a
// get_first x:xs = x
template<class SEQ_C>
struct get_first {
enum { value = -1 };
typedef get_first<SEQ_C> type;
typedef typename SEQ_C::value_type value_type;
typedef SEQ_C sequence_type;
};
//needed for char/short/int/long
template<template<class T, long... S> class SEQ_C, class T0, long X, long... XS>
struct get_first<SEQ_C<T0, X, XS...>> {
enum { value = X };
typedef get_first<SEQ_C<T0, X, XS...>> type;
typedef T0 value_type;
typedef SEQ_C<T0, X, XS...> sequence_type;
};
//needed for long long
template<template<class T, T... S> class SEQ_C, class T0, T0 X, T0... XS>
struct get_first<SEQ_C<T0, X, XS...>> {
enum { value = X };
typedef get_first<SEQ_C<T0, X, XS...>> type;
typedef T0 value_type;
typedef SEQ_C<T0, X, XS...> sequence_type;
};
对get_first<SEQ>::sequence_type
进行解码非常有启发性。为此,我发现这段代码非常有用(如果你不想一直使用c ++ filt):
#include<typeinfo>
#include<string>
#include<cstdlib>
#include<cxxabi.h>
std::string demangle(const char* name) {
int status;
char *realname;
std::string retValue;
realname = abi::__cxa_demangle(name, NULL, NULL, &status);
if (realname != NULL) {
retValue = std::string(realname);
free(realname);
}
return retValue;
}
template<class T>
std::string demangle() { return demangle(typeid(T).name()); }
非常感谢很快就有98%的人在那里。