在这个例子中:
template<typename T>
struct ConditionalValue
{
typedef boost::optional<T> type;
};
template<typename T>
struct FindRootValueType
{
typedef typename T::root_type type;
};
template<typename T>
struct FindRootValueType<typename ConditionalValue<T>::type>
{
typedef typename ConditionalValue<T>::type type;
};
template<typename T>
struct Base
{
typedef T value_type;
typedef typename FindRootValueType<value_type>::type root_type;
std::vector<value_type> data;
};
template<typename T>
struct A : public Base<typename ConditionalValue<T>::type>
{
};
template<typename T>
struct B : public Base<A<T>>
{
};
template<typename T>
struct C : public Base<B<T>>
{
};
// C<int>::value_type == B<int>
// C<int>::data == std::vector<B<int>>
// C<int>::data ~= std::vector<std::vector<std::vector<boost::optional<int>>>>
// C<int>::root_type == boost::optional<int>
ConditionalValue
是一个模板别名,它只是尝试为boost::optional
提供一个替代名称(这样可以使用其他内容替换它),而FindRootValueType
是一个旨在用于替换它的元函数向上走一系列类型,这些类型的定义与底部显示的定义类似,直到它停在boost::optional
,然后只返回它。
然而,正如所写,这不起作用(至少在VS2008中没有)。要修复它,FindRootValueType的特化必须显式使用boost::optional<T>
,而不是应该等效的typedef。 (这会破坏仅在一个地方指定底层实现类型的目标。)
这是编译器错误还是应该不起作用?或者我只是做错了什么?是否有更好的方法来编写它以使其按预期工作?
我也尝试过逆转逻辑:
template<typename T>
struct FindRootValueType
{
typedef T type;
};
// define Base here
template<typename T>
struct FindRootValueType<Base<T>>
{
typedef typename T::root_type type;
};
// define A here
template<typename T>
struct FindRootValueType<A<T>>
{
typedef T type;
};
// define B, C here (no specialisation)
但这也不起作用(我认为因为专业化不遵循基本类型,或者可能只是定义的顺序)。我不想特别专注于B,C等。
(顺便说一下,在上述两种情况下,“不工作”意味着产生的编译器错误表明它使用的是FindRootValueType
的基本定义,而不是专业化。)
答案 0 :(得分:0)
受到this answer启发的相关问题链接,我尝试了以下操作,似乎有效:
template<typename T>
struct HasRootType
{
private:
typedef char no;
struct yes { no m[2]; };
static T* make();
template<typename U>
static yes check(U*, typename U::root_type* = 0);
static no check(...);
public:
static bool const value = sizeof(check(make())) == sizeof(yes);
};
template<typename T, bool = HasRootType<T>::value>
struct FindRootValueType
{
typedef typename T::root_type type;
};
template<typename T>
struct FindRootValueType<T, false>
{
typedef T type;
};
// define Base, A, B, C, etc here
因此,重新定义问题“向前走,直到找到没有root_type
的类型,然后返回”。我仍然很好奇为什么基于typedef的专业化似乎不起作用。