Saya mencoba melakukan sesuatu seperti ini:
#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;
}
tapi saya mendapatkan kesalahan ini:
error: missing binary operator before token "("
Bagaimana saya bisa membuat typedef bersyarat dengan benar?
sizeof
, atau konstruksi C ++ lainnya. Itu pasti tidak tahu tentang hal-hal yang Anda buat sendiritypedef
, karena itu bahkan belum diuraikan.enable_if
atauconditional
untuk mendefinisikan typedef secara bersyarat, tetapi Anda tidak dapat menggunakan preprocessor untuk itu.sizeof
tidak dapat bekerja dalam kondisi preprocessor adalah karena bahasanya didefinisikan seperti itu, bukan karena cara kerja implementasi.Jawaban:
Gunakan
std::conditional
meta-function dari C ++ 11.#include <type_traits> //include this typedef std::conditional<sizeof(int) <= 4, std::mt19937, std::mt19937_64>::type Engine;
Perhatikan bahwa jika tipe yang Anda gunakan
sizeof
adalah parameter template, katakanlahT
, Anda harus menggunakantypename
sebagai:typedef typename std::conditional<sizeof(T) <= 4, // T is template parameter std::mt19937, std::mt19937_64>::type Engine;
Atau
Engine
bergantung padaT
:template<typename T> using Engine = typename std::conditional<sizeof(T) <= 4, std::mt19937, std::mt19937_64>::type;
Itu fleksibel , karena sekarang Anda bisa menggunakannya sebagai:
Engine<int> engine1; Engine<long> engine2; Engine<T> engine3; // where T could be template parameter!
sumber
sizeof(int) <= 4
mungkin bukan cara yang sangat portabel karena pada mesin Windows 64-bit, kompiler GCC (MinGW) x64 memberikansizeof(int) = sizeof(long) = 4
. Cara yang lebih baik adalahsizeof(void*) <= 4
.Engine<void*> engine4;
? ;-)std::conditional<sizeof(void*) <= 4, std::mt19937, std::mt19937_64>
di potongan kode pertama.Engine<void*>
? : Pint
:)Menggunakan
std::conditional
Anda dapat melakukannya seperti ini:using Engine = std::conditional<sizeof(int) <= 4, std::mt19937, std::mt19937_64 >::type;
Jika Anda ingin melakukan
typedef
, Anda juga dapat melakukannya.typedef std::conditional<sizeof(int) <= 4, std::mt19937, std::mt19937_64 >::type Engine
sumber
typename
siniJika Anda tidak memiliki C ++ 11 yang tersedia (meskipun tampaknya Anda melakukannya jika Anda berencana untuk menggunakan
std::mt19937
), maka Anda dapat mengimplementasikan hal yang sama tanpa dukungan C ++ 11 menggunakan Boost Metaprogramming Library (MPL) . Berikut adalah contoh kompilasi:#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; }
Ini mencetak nama yang rusak
foo
di sistem saya, sebagaiint
4 byte di sini.sumber
if_c
saja? Ini akan menjadi keharusan mudah untuk menulis (dan memahami):mpl::if_c<sizeof(int)<=4, foo, bar>::type
. Bukan?mpl::if_c
. Saya memperbarui contoh untuk menggunakan pendekatan itu sebagai gantinya.