[英]C++ how to emulate a function without implicit conversions?
我正在尝试使用函数模板(或其他一些模板化的结构)来模拟一个函数,而没有对参数或返回表达式进行隐式转换。 最有效的方法是什么?
理想情况下,我正在尝试提出一种易于隐藏在模板或宏后面,具有不错的错误消息并且不施加运行时间损失的方法。
这旨在作为元编程练习; 我不会在生产代码中这样做。
下面的函数func1
需要两个longs
,并将它们加在一起,照常执行转换。
long func1(long a, long b) {
return a + b;
}
我想以这样的方式定义func
: a
和b
只能是long
s,并在编译时检查return
表达式确实具有指示的类型,而无需插入隐式转换。
为了具体起见,到目前为止,我已经尝试了几种方法来完成这些工作。
防止转换的一种方法(仅适用于自变量)是使用带有已删除实现的函数模板,以及对自变量组合进行专门化处理的函数模板。
template <class L1, class L2>
long func2(L1 a, L2 b) = delete;
template<>
long func2(long a, long b) {
return a + b;
}
也可以使用enable_if
完成同一件事。
template <class L1, class L2>
std::enable_if_t<
std::is_same<L1, long>::value && std::is_same<L2, long>::value
, long> func3(L1 a, L2 b) {
return a + b;
}
但是,我无法弄清楚如何合并一个关于返回类型的断言,而不会使自己付出复制或搬家的代价,或者需要做复杂的事情来剥夺CV资格和参考性。
// doesn't work, unnecessary copy
template <class L1, class L2>
std::enable_if_t<
std::is_same<L1,long>::value && std::is_same<L2,long>::value,
long> func4(L1 a, L2 b) {
auto out = a + b;
static_assert(std::is_same<decltype(out), long>::value);
return out;
}
但是,我可以将函数主体移到lambda中,然后使用static_assert
列出我想要的所有条件。 我有点担心这种方法会出乎意料。
template <class L1, class L2>
long func5(L1 a, L2 b) {
static auto wrapped = [&](){
return a + b;
};
static_assert(std::is_same<decltype(a), long>::value);
static_assert(std::is_same<decltype(b), long>::value);
static_assert(std::is_same<decltype(wrapped()), long>::value);
return wrapped();
}
可能有很多方法可以做到这一点。 这是一个 我认为没有任何理由检查所有这些情况。 您想对const-volatile限定符做什么? 允许还是不允许?
#include <type_traits>
#include <iostream>
template<typename Long>
Long func1(Long a, Long b) {
static_assert(std::is_same_v<Long, long>);
return a + b;
}
int main()
{
long a = 1;
const long b = 2;
const long &c = a;
std::cout << func1(c,b) << std::endl;
}
无需lambda:
template <class L1, class L2>
long func2(L1, L2) = delete;
decltype(auto) func2(long a, long b) {
return a + b;
}
static_assert(std::is_same<long, decltype(func2(42L, std::declval<long>()))>::value);
无需生成临时测试其类型,只需使用decltype
template <class L1, class L2>
auto func3(L1 a, L2 b)
-> std::enable_if_t<
std::is_same<L1, long>::value &&
std::is_same<L2, long>::value &&
std::is_same<decltype(a+b), long>::value,
long>
{
return a + b;
}
或使用static_assert
:
template<typename T1, typename T2>
void func(T1, T2) = delete;
long func(long a, long b)
{
static_assert(std::is_same<long,decltype(a+b)>::value,"!!");
return a+b;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.