Я не рекомендую такой подход, но я нашел способ, который будет работать, даже если у вас нет C ++ 17. Вы можете использовать макрос (как упомянуто в вопросе), если вы хотите просто заменить текст и у вас есть C ++ 17. В противном случае вы можете сделать это так, если не возражаете против немного другого синтаксиса:
template<int LENGTH = 1>
struct MyStruct{ int arr[LENGTH]; };
#define MyAlias(...) MyStruct<__VA_ARGS__>
using MyAlias = MyStruct<>;
int main()
{
MyAlias(2) a; // MyAlias<2>
MyAlias() b; // MyAlias<>
MyAlias c;
}
Есть несколько преимуществ по сравнению с другими подходами:
- Вам не нужен C ++ 17
- Вам не нужно заново указывать значения по умолчанию (DRY
принцип)
- Вам не нужны дополнительные классы, функции и т. Д.
- Может сочетаться с обходным путем для специализации псевдонимов шаблонов
В качестве примера представьте, что вы хотите создать класс для эмуляции чисел с плавающей запятой различных размеров. Если размер соответствует встроенному типу, вы хотите использовать это непосредственно для эффективности, в противном случае вы используете свой класс. Кроме того, вы хотите, чтобы размер по умолчанию был самым эффективным на вашей платформе, чтобы уменьшить детализацию.
В идеале я бы хотел иметь возможность использовать шаблоны псевдонимов:
template<int BITS>
struct BasicReal final
{
constexpr BasicReal(const double){};
};
template<int BITS = 64>
using Real = BasicReal<BITS>;
template<> // Alias template specialization if it worked
using Real<64> = double;
template<> // Alias template specialization if it worked
using Real<32> = float;
int main()
{
Real r = 1.2; // Alias template argument deduction if it worked
Real<16> r16 = 1.2;
Real<32> r32 = 1.2;
Real<64> r64 = 1.2;
return r;
}
Однако сейчас я могу использовать следующий обходной путь (даже в C ++ 11):
template<int BITS>
struct BasicReal final
{
constexpr BasicReal(const double){};
};
template<int BITS = 64>
struct RealAlias
{
using Type = BasicReal<BITS>;
};
template<>
struct RealAlias<64>
{
using Type = double;
};
template<>
struct RealAlias<32>
{
using Type = float;
};
#define Real(...) RealAlias<__VA_ARGS__>::Type
using Real = RealAlias<>::Type;
int main()
{
Real r = 1.2;
Real(16) r16 = 1.2;
Real(32) r32 = 1.2;
Real(64) r64 = 1.2;
return r;
}