【发布时间】:2018-11-27 18:00:32
【问题描述】:
我有一个采用非类型模板参数的模板方法。 它具有以下形式:
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 解决方案来了解是否可以做到这一点。
下面缺少的是类型匹配的编译时检查。但是,主要的语法是我想要的。
#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 类不是一个简单的结构。并且构建它所需的值在编译时是已知的。这就是我想到使用非类型模板的原因。
【问题讨论】:
-
有关于“强类型整数”的问题。 stackoverflow.com/search?q=strongly+typed+integer。希望您没有重新发明轮子。
-
或者使用枚举作为包装整数的强类型?我当然建议使用带值的枚举来包装布尔值。在源代码中几乎没有比
Setup(true, false, 1, false, 55000)更糟糕的了,比Setup(Screen::ON, Mike::OFF, Brightness {1}, Camera::OFF, Distance{ 55000})好很多
标签: c++ c++11 templates c++14 c++17