我是metafunctions的新手。我想编写一个函数,用一些其他类型替换复合类型中某种类型的所有匹配项。例如:replace<void *, void, int>::type
应为int *
,replace<void, void, int>::type
应为int
等。
到目前为止,我基本上失败了两种不同的方法:
template
<
typename C, // Type to be searched
typename X, // "Needle" that is searched for
typename Y // Replacing type
>
struct replace
{
typedef C type;
};
// If the type matches the search exactly, replace
template
<
typename C,
typename Y
>
struct replace<C, C, Y>
{
typedef Y type;
};
// If the type is a pointer, strip it and call recursively
template
<
typename C,
typename X,
typename Y
>
struct replace<C *, X, Y>
{
typedef typename replace<C, X, Y>::type * type;
};
这对我来说非常简单,但我发现当我尝试replace<void *, void *, int>
时,编译器无法决定在这种情况下是使用replace<C, C, Y>
还是replace<C *, X, Y>
,因此编译失败。
我接下来要尝试的是在基函数中删除指针:
template
<
typename C,
typename X,
typename Y
>
struct replace
{
typedef typename boost::conditional
<
boost::is_pointer<C>::value,
typename replace
<
typename boost::remove_pointer<C>::type,
X, Y
>::type *,
C
>::type
type;
};
...而且当我发现我也不能这样做时,因为type
显然没有在那时被定义,所以我不能从基函数中做递归typedef
。 / p>
现在我没有想法。你会如何解决这个问题?
答案 0 :(得分:3)
这是一个大致的想法:
template <typename, typename> struct pattern;
template <typename T> struct pattern<T, T>
{
template <typename U> struct rebind
{
typedef U other;
};
};
template <typename A, typename B> struct pattern<A*, B>
{
template <typename U> struct rebind
{
typedef typename pattern<A, B>::template rebind<U>::other * other;
};
};
template <typename Haystack, typename Needle, typename New>
struct replace
{
typedef typename pattern<Haystack, Needle>::template rebind<New>::other type;
};
测试:
#include <demangle.hpp>
#include <iostream>
int main()
{
typedef replace<void, void, int>::type T1;
typedef replace<void*, void, int>::type T2;
std::cout << demangle<T1>() << std::endl;
std::cout << demangle<T2>() << std::endl;
}
打印:
int
int*
编辑:这是一套更完整的内容:
template <typename, typename> struct pattern;
template <typename, typename> struct pattern_aux;
template <typename A, typename B> struct pattern_aux
{
template <typename U> struct rebind
{
typedef typename pattern<A, B>::template rebind<U>::other other;
};
};
template <typename A, typename B, unsigned int N> struct pattern_aux<A[N], B>
{
template <typename U> struct rebind
{
typedef typename pattern<A, B>::template rebind<U>::other other[N];
};
};
template <typename A, typename B> struct pattern
{
template <typename U> struct rebind
{
typedef typename pattern_aux<A, B>::template rebind<U>::other * other;
};
};
template <typename T> struct pattern<T, T>
{
template <typename U> struct rebind
{
typedef U other;
};
};
template <typename A, typename B> struct pattern<A*, B>
{
template <typename U> struct rebind
{
typedef typename pattern<A, B>::template rebind<U>::other * other;
};
};
template <typename A, typename B> struct pattern<A const, B>
{
template <typename U> struct rebind
{
typedef typename pattern_aux<A, B>::template rebind<U>::other const other;
};
};
template <typename A, typename B> struct pattern<A volatile, B>
{
template <typename U> struct rebind
{
typedef typename pattern_aux<A, B>::template rebind<U>::other volatile other;
};
};
template <typename A, typename B> struct pattern<A const volatile, B>
{
template <typename U> struct rebind
{
typedef typename pattern_aux<A, B>::template rebind<U>::other const volatile other;
};
};
template <typename Haystack, typename Needle, typename New>
struct replace
{
typedef typename pattern<Haystack, Needle>::template rebind<New>::other type;
};
答案 1 :(得分:1)
你尝试过的东西:
#include <typeinfo>
#include <type_traits>
template<typename C, typename X, typename Y>
struct replace {
private:
typedef
typename std::conditional <
std::is_pointer<C>::value,
typename std::remove_pointer<C>::type,
C >::type
strippedT;
typedef
typename std::conditional <
std::is_same<strippedT, X>::value,
Y,
strippedT>::type
replacedT;
public:
typedef
typename std::conditional <
std::is_pointer<C>::value,
replacedT*,
replacedT >::type
type;
};
int main()
{
typedef replace<void*, void, int>::type T1;
std::cout << typeid(T1).name() << '\n'; // prints Pi on my implementation
typedef replace<void, void, int>::type T2;
std::cout << typeid(T2).name(); // prints i
}
Kerrek的回答看起来好多了:)
答案 2 :(得分:0)
关注您的代码,为什么不再添加一个专业化
template
<
typename C,
typename Y
>
struct replace<C*, C, Y>
{
typedef Y* type;
};
实时代码example results
或更多:
template<class T>
struct tag_t {using type=T;};
template <class C, class X, class Y>
struct replace {};
template <class C, class Y>
struct replace<C, C, Y>: tag_t<Y> {};
template <class C, class Y>
struct replace<C*, C, Y>: tag_t<Y*>{};
实时代码results