У меня есть шаблонный метод, принимающий не типовые аргументы шаблона.Он имеет следующий вид:
template <long long connectionTimeout, long long sendTimeout, bool autoAck>
void create() { ... }
Это служебная функция в другом заголовке, и меня раздражает в коде вызывающей стороны то, что константы не набираются.
Значение вместоэтот способ вызова:
create<1, 2, true>();
Я предпочитаю иметь следующее:
create<
connection_timeout {1},
send_timeout {2},
auto_ack {true}
>();
С функцией create
, гарантирующей, что send_timeout
не может быть передан вместо connection_timeout
.
Однако я начал писать доказательство концепции с некоторыми пробелами.Я хотел бы заставить его работать с C ++ 11/14.Однако мне пришлось использовать конструкции C ++ 17 (код cf), чтобы все работало до сих пор.При этом я не возражаю против решений C ++ 17, чтобы получить представление о том, можно ли это сделать.
Чего не хватает в следующем, так это проверки времени компиляции на соответствие типов.Тем не менее, синтаксис в main - это то, что я хотел бы иметь.
#include <iostream>
#include <string>
template <typename T, T userSpecifiedValue>
struct compile_time_constant_wrapper
{
using type = T;
static const T defaultValue = userSpecifiedValue;
constexpr operator T() const
{
return value;
}
T value = defaultValue;
};
using connection_timeout = compile_time_constant_wrapper<long long, 5000>;
using send_timeout = compile_time_constant_wrapper<long long, 10>;
using auto_ack = compile_time_constant_wrapper<bool, false>;
struct ComplicatedToBuild
{
long long connectionTimeout;
long long sendTimeout;
bool autoAck;
};
template <typename T,
long long connectionTimeout = connection_timeout {} /*-std=c++17*/,
long long sendTimeout = send_timeout {} /*-std=c++17*/,
bool autoAck = auto_ack {} /*-std=c++17*/>
struct create
{
operator T() const
{
return T{connectionTimeout, sendTimeout, autoAck};
}
};
std::ostream& operator<<(std::ostream& out, const ComplicatedToBuild& complicated)
{
out << "connection timeout = " << complicated.connectionTimeout << ", "
<< "send timeout = " << complicated.sendTimeout << ", "
<< "auto ack = " << complicated.autoAck;
return out;
}
int main()
{
ComplicatedToBuild defaultValuesCase = create<ComplicatedToBuild>();
std::cout << "defaultValuesCase: " << defaultValuesCase << std::endl;
ComplicatedToBuild customizedCase = create<
ComplicatedToBuild,
connection_timeout {2500},
send_timeout {5},
auto_ack {true}
>();
std::cout << "customizedCase: " << customizedCase << std::endl;
ComplicatedToBuild compilationErrorCase = create<
ComplicatedToBuild,
send_timeout {5},
connection_timeout {2500},
auto_ack {true}
>();
}
В моем случае класс ComplicatedToBuild
не является простой структурой.И значения, необходимые для его построения, известны во время компиляции.Вот почему я подумал об использовании не типовых шаблонов.