繁体   English   中英

C ++如何模拟没有隐式转换的函数?

[英]C++ how to emulate a function without implicit conversions?

我正在尝试使用函数模板(或其他一些模板化的结构)来模拟一个函数,而没有对参数或返回表达式进行隐式转换。 最有效的方法是什么?

理想情况下,我正在尝试提出一种易于隐藏在模板或宏后面,具有不错的错误消息并且不施加运行时间损失的方法。

这旨在作为元编程练习; 我不会在生产代码中这样做。

下面的函数func1需要两个longs ,并将它们加在一起,照常执行转换。

long func1(long a, long b) {
  return a + b;
}

我想以这样的方式定义funcab只能是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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM