C++ C++;

C++ C++;,c++,templates,c++11,C++,Templates,C++11,我有一个模板类,只有当模板参数满足某些条件时,某些成员函数才有意义。例如,使用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

我有一个模板类,只有当模板参数满足某些条件时,某些成员函数才有意义。例如,使用
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
{
typename std::enable_if::键入一个_成员();
使另一个成员无效()
{
a_member();//如何将此限制为仅允许的情况?
}
};

首先,不能像那样使用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"
}
模板类别A
{
私人:
样板
typename std::enable_if::type a_成员(){
std::cout::键入a_成员(){
//无所事事
}
公众:
使另一个成员无效()
{
a_成员();
}
};
int main(){
不可能;
不是。另一个_成员();//不打印任何内容
漂浮物;
漂浮。另一个_成员();//打印“正在做某事”
}

首先,不能像那样使用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"
}
模板类别A
{
私人:
样板
typename std::enable_if::type a_成员(){
std::cout::键入a_成员(){
//无所事事
}
公众:
使另一个成员无效()
{
a_成员();
}
};
int main(){
不可能;
不是。另一个_成员();//不打印任何内容
漂浮物;
漂浮。另一个_成员();//打印“正在做某事”
}
警告:这是一个完整、可怕的黑客攻击,我没有尝试过,可能永远不会奏效。 尝试将其添加到类声明中:

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
  }
}
typename std::enable_if::type a_enabled_p(){return 0;};
使另一个无效()
{
如果((a_启用的_p()+1)==1)
{
//未启用
}
else if((a_enabled_p()+1)=sizeof(int))
{
//已启用
}
}
这就是为什么这种恐惧可能会起作用。如果它们是浮点,谓词的返回值是一个
int*
。如果它们是,则没有typedef,它默认为
int
(我希望如此)。当您向
int*
添加1时,实际上是在添加
sizeof(int)
。向整数中添加1会增加1。这意味着通过检查添加1的值,我们知道

注意:不要用这个。想出这个答案很有趣,但上面的答案非常非常有趣

很 更好。请不要使用它。

警告:这是一个完整的、可怕的黑客攻击,我没有尝试过,可能永远不会奏效。 尝试将其添加到类声明中:

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
  }
}
typename std::enable_if::type a_enabled_p(){return 0;};
使另一个无效()
{
如果((a_启用的_p()+1)==1)
{
//未启用
}
else if((a_enabled_p()+1)=sizeof(int))
{
//已启用
}
}
这就是为什么这种恐惧可能会起作用。如果它们是浮点,谓词的返回值是一个
int*
。如果它们是,则没有typedef,它默认为
int
(我希望如此)。当您向
int*
添加1时,实际上是在添加
sizeof(int)
。向整数中添加1会增加1。这意味着通过检查添加1的值,我们知道

注意:不要用这个。想出这个答案很有趣,但上面的答案非常非常有趣



更好。不要使用此选项。请。

是否要在编译时删除它们、在编译时出错或在运行时知道?为其余类型(非浮点)提供空的a_成员重载如何.@Linuxios只是不在运行时调用它们,而在编译时不存在这种类型。@mfontanini你能让我的示例使用它吗?Joe的答案正是我的意思:D.你想在编译时删除它们,在编译时出错,还是在运行时知道?为其余类型提供一个空的a_成员重载怎么样(不是浮点)。@Linuxios只是在运行时不调用它们,编译时不存在这种类型的代码。@MFontani你能让我的示例使用它吗?Joe的回答正是我的意思:D.这是一个运行时版本,不会编译(你的“未启用”代码不仅没有调用,而且仍然启用)@Walter:我从来没有说过它会起作用,但为什么?如何?这是我第一次看到
std::enable_if
,所以请告诉我。这是一个运行时版本,不会编译(你的“未启用”代码不仅不会调用,而且仍然启用)@Walter:我从未说过它会起作用,但为什么?如何?这是我第一次看到
std::enable_if
,所以请启发我。+1太好了!我试过了,但没有在S上添加额外的模板,这对避免函数重载至关重要。额外的模板参数不是为了避免不明确的重载。SFINAE只对函数起作用模板,而不是类模板,所以您需要将这些函数制作成模板。这是语义。为了使用SFINAE,需要不同的函数签名,而不明确的重载不能给出这一点(我的编译器(gcc/4.7.0)抱怨重载)@沃尔特:它不是语义- SfANA只对模板函数起作用。如果通过给两个非模板函数提供不同的参数列表来解决过载模糊,它仍然不起作用。如果有一个C++语言标准(从D语言设计者)的命题,那么就可以很好地完成这个答案。添加著名的static if比enable if要优雅得多。+1太好了!我试过了,但是没有在S上添加额外的模板,这对于避免函数重载是至关重要的。额外的模板参数不是为了避免不明确的重载。SFINAE只在函数模板上工作,而不是类模板,所以你需要让它们变得有趣ctions templates.this is is semantics.为了使用SFINAE,需要不同的函数签名,而不明确的重载不能给出(我的编译器(gcc/4.7.0)抱怨重载)。@Walter:这不是语义-SFINAE只对模板函数起作用。如果你解决了这个问题