如何在 C + + 中创建条件 typedef

我正在尝试做这样的事情:

#include <iostream>
#include <random>


typedef int Integer;


#if sizeof(Integer) <= 4
typedef std::mt19937     Engine;
#else
typedef std::mt19937_64  Engine;
#endif


int main()
{
std::cout << sizeof(Integer) << std::endl;
return 0;
}

但我得到了这个错误:

error: missing binary operator before token "("

如何正确地使用条件 typedef?

17662 次浏览

Use the std::conditional meta-function from C++11.

#include <type_traits>  //include this


typedef std::conditional<sizeof(int) <= 4,
std::mt19937,
std::mt19937_64>::type Engine;

Note that if the type which you use in sizeof is a template parameter, say T, then you have to use typename as:

typedef typename std::conditional<sizeof(T) <= 4, // T is template parameter
std::mt19937,
std::mt19937_64>::type Engine;

Or make Engine depend on T as:

template<typename T>
using Engine = typename std::conditional<sizeof(T) <= 4,
std::mt19937,
std::mt19937_64>::type;

That is flexible, because now you can use it as:

Engine<int>  engine1;
Engine<long> engine2;
Engine<T>    engine3; // where T could be template parameter!

Using std::conditional you can do it like so:

using Engine = std::conditional<sizeof(int) <= 4,
std::mt19937,
std::mt19937_64
>::type;

If you want to do a typedef, you can do that too.

typedef std::conditional<sizeof(int) <= 4,
std::mt19937,
std::mt19937_64
>::type Engine

If you don't have C++11 available (although it appears you do if you're planning to use std::mt19937), then you can implement the same thing without C++11 support using the Boost Metaprogramming Library (MPL). Here is a compilable example:

#include <boost/mpl/if.hpp>
#include <iostream>
#include <typeinfo>


namespace mpl = boost::mpl;


struct foo { };
struct bar { };


int main()
{
typedef mpl::if_c<sizeof(int) <= 4, foo, bar>::type Engine;


Engine a;
std::cout << typeid(a).name() << std::endl;
}

This prints the mangled name of foo on my system, as an int is 4 bytes here.