sma*_*llB 7 c++ metaprogramming
如何在编译器中获取最大可用类型的名称?有可能吗?
就像是:
auto largest = get_largest_type();
Run Code Online (Sandbox Code Playgroud)
在我的情况下,汽车会很长.
好吧,根据你需要的程度,你可以在这里尝试一些严肃的元编程......
首先,您显然需要某种定义所有可用基元类型的“包”,所以这里是:
template<typename... TYPES>
class pack
{};
typedef pack<float, double, long double, unsigned short, unsigned int,
unsigned long, unsigned long long, short, int, long, long long> primitive_types;
Run Code Online (Sandbox Code Playgroud)
然后,您将需要一种方法来根据大小对这些类型进行排序,因此首先,让我们定义一个元函数,能够对大小实现严格的弱排序:
template<typename L, typename R>
class smaller
{
public:
static const bool value = sizeof(L) < sizeof(R);
};
Run Code Online (Sandbox Code Playgroud)
现在,排序算法。在这里,我任意选择了合并排序,这需要 3 个其他元功能:pack_cat用于连接包、pack_merge根据顺序合并它们以及halve将包分解为另外 2 个包。
template<typename, typename>
class pack_cat;
template<typename... L, typename... R>
class pack_cat<pack<L...>, pack<R...>>
{
public:
typedef pack<L..., R...> type;
};
template<template<typename, typename> class, typename, typename>
class pack_merge;
template<template<typename, typename> class MF, typename HL, typename... TL, typename HR, typename... TR>
class pack_merge<MF, pack<HL, TL...>, pack<HR, TR...>>
{
public:
typedef typename std::conditional<MF<HR, HL>::value,
typename pack_cat<pack<HR>, typename pack_merge<MF, pack<HL, TL...>, pack<TR...>>::type>::type,
typename pack_cat<pack<HL>, typename pack_merge<MF, pack<TL...>, pack<HR, TR...>>::type>::type>::type type;
};
template<template<typename, typename> class MF, typename H, typename... T>
class pack_merge<MF, pack<H, T...>, pack<>>
{
public:
typedef pack<H, T...> type;
};
template<template<typename, typename> class MF, typename... R>
class pack_merge<MF, pack<>, pack<R...>>
{
public:
typedef pack<R...> type;
};
template<typename>
class halve;
template<typename A, typename B, typename... T>
class halve<pack<A, B, T...>>
{
public:
typedef typename pack_cat<pack<A>, typename halve<pack<T...>>::L>::type L;
typedef typename pack_cat<pack<B>, typename halve<pack<T...>>::R>::type R;
};
template<typename T>
class halve<pack<T>>
{
public:
typedef pack<T> L;
typedef pack<> R;
};
template<>
class halve<pack<>>
{
public:
typedef pack<> L;
typedef pack<> R;
};
template<template<typename, typename> class MF, typename P>
class pack_sort
{
private:
typedef typename halve<P>::L L;
typedef typename halve<P>::R R;
public:
typedef typename pack_merge<MF, typename pack_sort<MF, L>::type, typename pack_sort<MF, R>::type>::type type;
};
template<template<typename, typename> class MF, typename H>
class pack_sort<MF, pack<H>>
{
public:
typedef pack<H> type;
};
template<template<typename, typename> class MF>
class pack_sort<MF, pack<>>
{
public:
typedef pack<> type;
};
Run Code Online (Sandbox Code Playgroud)
最后,您将需要一个元函数来检索包的最后一个参数,这很容易实现:
template<typename>
class pack_get_last;
template<typename H, typename... T>
class pack_get_last<pack<H, T...>>
{
public:
typedef typename pack_get_last<pack<T...>>::type type;
};
template<typename H>
class pack_get_last<pack<H>>
{
public:
typedef H type;
};
Run Code Online (Sandbox Code Playgroud)
现在,一个测试程序可以向您证明我在那里编写的所有这些垃圾代码确实有效:
#include <iostream>
#include <utility>
/* all those metafunctions come here */
int main()
{
typename pack_get_last<typename pack_sort<smaller, primitive_types>::type>::type largest;
if(std::is_same<decltype(largest), long double>::value)
std::cout << "MATCH!\n";
}
Run Code Online (Sandbox Code Playgroud)
使用 gcc 4.6 在 x64 Linux 机器中输出,其中 long double 是最大的可用简单基元类型:
MATCH!
Run Code Online (Sandbox Code Playgroud)