我想一个模板,基于某些条件下两种选择。 例如
struct Base {};
template <typename T1, typename T2>
struct test
{
// e.g. here it should select T1/T2 that is_base_of<Base>
typename select_base<T1, T2>::type m_ValueOfBaseType;
};
当然,要条件传递给select_base(使它通用)是有用的,但硬编码的解决方案更容易,以及良好。
下面是我试过的样品溶液,但它总是选择T1: http://ideone.com/EnVT8
现在的问题是如何实现select_base模板。
C ++ 14(以及以后):
template <typename T, typename U>
struct select_base:
std::conditional_t<std::is_base_of<T, Base>::value, T, U> {};
本着同样的精神,你可以使用它代替:
template<typename T, typename U>
using select_base = std::conditional_t<std::is_base_of_v<T,Base>, T, U>;
当您使用它们可以看出这两种方法之间的差异。 例如,在第一种情况下,如果你必须使用::type
,而在第二个,你不。 如果有任何依赖型的第一种方法的使用涉及,你必须使用typename
为好,以协助编译器。 第二种方法是免费的所有这样的噪声,因而优于这个答案的方法的其余部分。
另外,请注意,您可以用C ++写11相似类型的别名也。
C ++ 11:
template <typename T, typename U>
struct select_base:
std::conditional<std::is_base_of<T, Base>::value, T, U>::type {};
// ^ ^~~~~~
C ++ 98:
条件是很容易做到:
template <typename bool, typename T, typename U>
struct conditional { typedef T type; };
template <typename T, typename U>
struct conditional<false, T, U> { typedef U type; };
is_base_of
要稍微复杂一些,实现在加速,我不会在这里重现可用。
然后,请参阅C ++ 11。
如果您使用std::conditional
,而不是if_
类模板由@Matthieu在他的回答中实现,那么你的解决方案会减少这样的:
template <typename T, typename U>
struct select_base
{
typedef typename std::conditional<std::is_base_of<T, Base>::value, T, U>::type base_type;
};
或者简单:
template <typename T, typename U>
struct select_base : std::conditional<std::is_base_of<T, Base>::value, T, U> {};
它看起来甚至更好。
这两种解决方案之间的区别是,在第一个解决方案你嵌套类型给程序员友好的名字,因为我已经给它base_type
,而在第二溶液中的嵌套类型仅仅是type
不看那个程序员-友好。
请注意,在上述两种解决方案,你已经使用嵌套类型如任一select_base<T,U>::base_type
(在第一溶液)或select_base<T,U>::type
(在第二溶液-正因为如此,如果你使用的typename
为你写自己在问题本身。
但是,如果改为使用模板的别名,定义如下:
template<typename T, typename U>
using base_type = typename std::conditional<std::is_base_of<T, Base>::value, T, U>::type;
然后就可以使用base_type<T,U>
没有任何嵌套型和typename
为:
template <typename T1, typename T2>
struct test
{
//typename select_base<T1, T2>::type m_ValueOfBaseType; //ugly!
base_type<T1, T2> m_ValueOfBaseType; //better
};
希望帮助。