我有一个类模板,如下所示:
template <Base>
struct foo : Base
{
typedef int some_type;
};
我有一个看起来像这样的基地:
struct some_base
{
typedef float some_type;
};
现在foo<some_base>::some_type
将为int
,因为派生的foo
会隐藏Base::some_type
。我想做的是,如果定义了Base::some_type
,请使用其他内容,在some_type
中将foo
定义为int
- 所以问题是,这是可能的吗? ?
我可以颠倒这种关系并为自己省去一些头痛,但在实际应用中它并不合乎逻辑......
答案 0 :(得分:3)
使用一些模板元编程可以做任何事情:)
首先编写一个元函数,确定某个类型是否具有名为“some_type”的嵌套类型。像这样:
template <typename T>
struct has_some_type
{
typedef char no; // type with sizeof == 1
typedef struct { char x[2]; } yes; // type with sizeof == 2
template <typename X, typename Y = typename X::some_type>
struct foo {};
template <typename X>
static yes test(foo<X>*);
template <typename X>
static no test(...);
static const bool value = (sizeof(test<T>(0)) == sizeof(yes));
};
现在你可以在派生类中做这样的事情:
template <typename T, bool has_some_type>
struct get_some_type;
template <typename T>
struct get_some_type<T, true>
{
typedef typename T::some_type type;
};
template <typename T>
struct get_some_type<T, false>
{
typedef int type; // the default type
};
template <typename base>
class derived : base
{
typedef typename get_some_type<base, has_some_type<base>::value>::type some_type;
...
};
答案 1 :(得分:2)
这应该有效:
struct sfinae_types
{
struct yes { char x; };
struct no { char x[2]; };
};
template<class T>
class has_some_type : sfinae_types
{
private:
template<class U>
static yes test(typename U::some_type *);
template<class U>
static no test(...);
public:
enum { value = (sizeof(yes) == sizeof(test<T>(0))) };
};
template<bool, class T, typename DT>
struct get_some_type
{
typedef DT type;
};
template<class T, typename DT>
struct get_some_type<true, T, DT>
{
typedef typename T::some_type type;
};
struct B1
{
};
struct B2
{
typedef float some_type;
};
template<typename T>
struct D : T
{
typedef typename get_some_type<has_some_type<T>::value, T, int>::type some_type;
};
#include<iostream>
#include<typeinfo>
int main()
{
std::cout << has_some_type<B1>::value << std::endl;
std::cout << typeid(D<B1>::some_type).name() << std::endl;
std::cout << has_some_type<B2>::value << std::endl;
std::cout << typeid(D<B2>::some_type).name() << std::endl;
return(0);
}
与HighCommander4在几秒钟内呈现的内容略有不同......
我想boost :: mpl可能会派上用场,并提供一些我手工制作的有用的TMP表达式。
答案 2 :(得分:1)
为struct foo
提供一个默认为int
的其他模板参数:
template <Base, Typedef = int>
struct foo : Base
{
typedef Typedef some_type;
};
然后foo<some_base, some_base::some_type>::some_type
为some_base::some_type
。