【问题标题】:compile-time conditional member function call in C++C ++中的编译时条件成员函数调用
【发布时间】:2012-07-06 14:07:21
【问题描述】:

我有一个模板类,它的某些成员函数只有在模板参数满足某些条件时才有意义。例如,使用std::enable_if<> 我只能为这些情况定义它们,但我如何有条件地调用它们呢?这是一个简单的例子

template<class T> class A
{
   typename std::enable_if<std::is_floating_point<T>::value>::type a_member();
   void another_member()
   {
     a_member(); // how to restrict this to allowed cases only?
   }
};

【问题讨论】:

  • 你想在编译时删除它们,在编译时出错,还是在运行时知道?
  • 如何为其余类型(不是浮点)提供一个空的 a_member 重载。
  • @Linuxios 只是不在运行时调用它们,在编译时这种类型不存在。
  • @mfontanini 你能让我的例子用这个吗?
  • 乔的回答正是我的意思:D.

标签: c++ templates c++11


【解决方案1】:

首先,你不能这样使用 SFINAE - 模板类型参数需要在函数上,而不是在类上。

完整的解决方案如下所示:

template<class T> class A
{
private:
   template <class S>
   typename std::enable_if<std::is_floating_point<S>::value>::type a_member() {
       std::cout << "Doing something";
   }

   template <class S>
   typename std::enable_if<!std::is_floating_point<S>::value>::type a_member() {
       //doing nothing
   }

public:
   void another_member()
   {
     a_member<T>();
   }
};


int main() {
    A<int> AInt;
    AInt.another_member();//doesn't print anything

    A<float> AFloat;
    AFloat.another_member();//prints "Doing something"
}

【讨论】:

  • +1 太棒了!我试过了,但没有在 S 上添加额外的模板,这对于避免函数重载至关重要。
  • 额外的模板参数不是为了避免模棱两可的重载。 SFINAE 仅适用于函数模板,不适用于类模板,因此您需要制作这些函数模板。
  • 这是语义。为了使用 SFINAE,需要不同的函数签名,而模棱两可的重载无法提供(我的编译器 (gcc/4.7.0) 抱怨重载)。
  • @Walter:这不是语义 - SFINAE 仅适用于模板函数。如果你通过给两个非模板函数不同的参数列表来解决重载歧义,它仍然不起作用。
  • 很高兴完成这个答案,因为下一个 C++ 标准(来自 D 语言设计者)有一个提议添加著名的静态如果这比启用要优雅得多如果。
【解决方案2】:

警告:这是一个完整的、可怕的 hack,我没有尝试过它可能永远不会奏效。

尝试将其添加到类声明中:

typename std::enable_if<std::is_floating_point<T>, int*>::type a_enabled_p() { return 0;};
void another()
{
  if((a_enabled_p()+1)==1)
  {
    //Not enabled
  }
  else if((a_enabled_p()+1)==sizeof(int))
  {
    //Is enabled
  }
}

这就是为什么这种恐怖可能会奏效。如果它们是浮点数,则谓词的返回值为int*。如果是,则没有 typedef,默认为 int(我希望如此)。当您将 1 添加到 int* 时,您实际上是在添加 sizeof(int)。将 1 添加到 int 会增加 1。这意味着通过检查加一的值,我们就知道了。

注意:不要使用这个。想出来很有趣,但上面的答案是很多,很多

很多

更好。不要使用这个。请。

【讨论】:

  • 这是一个运行时版本,不会编译(您的“未启用”代码只是没有被调用,但仍然启用)。
  • @Walter:我从来没有说过它会起作用,但为什么呢?如何? std::enable_if我还是第一次见,请多多指教。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-21
  • 2018-08-25
  • 2019-04-30
相关资源
最近更新 更多