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

时间:2018-02-19 23:15:38

标签: c++ template-meta-programming

我正在尝试使用函数模板(或其他一些模板化构造)来模拟函数,而不会将隐式转换应用于参数或返回表达式。最有效的方法是什么?

理想情况下,我正在尝试提供一种方法来执行此操作,这很容易隐藏在模板或宏后面,具有相当不错的错误消息,并且不会对运行时造成惩罚。

这是一个元编程练习;我不会在生产代码中这样做。

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

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

我想以funca只能b的方式定义long并在编译时检查return } expression确实具有指定的类型而没有插入隐式转换。

为了具体起见,我到目前为止已尝试过两种方式,而且这里是。

阻止转换的一种方法(仅针对参数)是使用具有已删除实现的函数模板和用于参数组合的特化。

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();
}

3 个答案:

答案 0 :(得分:2)

可能有很多方法可以做到这一点。这是一个。我不认为有任何理由检查所有这些案件。你想对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;
}

答案 1 :(得分:1)

不需要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);

答案 2 :(得分:0)

无需生成临时测试其类型,只需使用tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener{ override fun onTabReselected(tab: TabLayout.Tab?) { } override fun onTabUnselected(tab: TabLayout.Tab?) { } override fun onTabSelected(tab: TabLayout.Tab) { when(tab.position){ 0->app_bar.setBackgroundColor(Color.parseColor("#FF0000")) 1->app_bar.setBackgroundColor(Color.parseColor("#4286f4")) 2->app_bar.setBackgroundColor(Color.parseColor("#f2ff00")) } } } )

即可
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