当前位置: 首页 > 知识库问答 >
问题:

使用不同的启用条件选择成员函数

黄俊智
2023-03-14

我试图根据类模板参数确定调用成员函数的哪个版本。我试过:

#include <iostream>
#include <type_traits>

template<typename T>
struct Point
{
  void MyFunction(typename std::enable_if<std::is_same<T, int>::value, T >::type* = 0)
  {
    std::cout << "T is int." << std::endl;
  }

  void MyFunction(typename std::enable_if<!std::is_same<T, int>::value, float >::type* = 0)
  {
    std::cout << "T is not int." << std::endl;
  }
};

int main()
{
  Point<int> intPoint;
  intPoint.MyFunction();

  Point<float> floatPoint;
  floatPoint.MyFunction();
}

我认为这是说“如果T是int,则使用第一个MyFunction,如果T不是int,则使用第二个MyFunction,但我收到编译器错误说“错误:在'结构std::enable_if'中没有名为'type'的类型”。有人能指出我在这里做错了什么吗?

共有3个答案

丰博
2023-03-14

我认为这遵循@Praetorian的解决方案,但我发现它更容易:

template<typename T>
struct Point
{
    template<typename U = T>
    std::enable_if_t<std::is_same<U, T>::value && std::is_same<T, int>::value>
    MyFunction()
    {
        std::cout << "T is int." << std::endl;
    }

    template<typename U = T>
    std::enable_if_t<std::is_same<U, T>::value && std::is_same<T, float>::value>
    MyFunction()
    {
        std::cout << "T is not int." << std::endl;
    }
};
罗诚
2023-03-14

一个简单的解决方案是使用工作人员私有函数的委托:

template<typename T>
struct Point
{

  void MyFunction()
  {
     worker(static_cast<T*>(nullptr)); //pass null argument of type T*
  }

private:

  void worker(int*)
  {
    std::cout << "T is int." << std::endl;
  }

  template<typename U>
  void worker(U*)
  {
    std::cout << "T is not int." << std::endl;
  }
};

Tint时,将调用第一个工作者函数,因为static_cast

艾星河
2023-03-14

enable_if之所以有效,是因为模板参数的替换导致了错误,因此替换从重载解析集中删除,编译器只考虑其他可行的重载。

在您的示例中,在实例化成员函数时不会发生替换,因为此时模板参数T已经已知。最简单的方法是创建一个默认为T的伪模板参数,并使用它来执行SFINAE。

template<typename T>
struct Point
{
  template<typename U = T>
  typename std::enable_if<std::is_same<U, int>::value>::type
    MyFunction()
  {
    std::cout << "T is int." << std::endl;
  }

  template<typename U = T>
  typename std::enable_if<std::is_same<U, float>::value>::type
    MyFunction()
  {
    std::cout << "T is not int." << std::endl;
  }
};

编辑:

正如HostileFork在评论中提到的,最初的示例允许用户显式指定成员函数的模板参数,并得到错误的结果。以下内容应防止编译成员函数的显式专门化。

template<typename T>
struct Point
{
  template<typename... Dummy, typename U = T>
  typename std::enable_if<std::is_same<U, int>::value>::type
    MyFunction()
  {
    static_assert(sizeof...(Dummy)==0, "Do not specify template arguments!");
    std::cout << "T is int." << std::endl;
  }

  template<typename... Dummy, typename U = T>
  typename std::enable_if<std::is_same<U, float>::value>::type
    MyFunction()
  {
    static_assert(sizeof...(Dummy)==0, "Do not specify template arguments!");
    std::cout << "T is not int." << std::endl;
  }
};
 类似资料:
  • 我希望使用Hibernate Criteria API从MySQL日期字段中获取所有不同的年份。这是我要转换为条件的查询: 我试过: 但它返回一个错误 错误-无法解析属性:年(日期):ca.ogsl.biodity.hibernate.Observation 有人知道这是否可能,以及如何做到吗? 谢谢!!! 基文

  • 问题内容: 我有两个这样的表,两个都是单独的表 另一个表包含以下结构 我需要从表II中选择AccountNo或TempAccountNo,Mycolumn,条件是 我需要选择 我需要选择 我该如何实现。 问题答案:

  • 在SQL中,我可以执行以下类型的查询: 因为,没有方法。或者如果我只是想: 有没有一种方法可以使用Jooq来做到这一点?

  • 我一直试图理解C++选择模板的方式。即,考虑以下代码示例: 前两个函数(test1)工作正常(为什么?): 一个常见的错误是声明两个仅在默认模板参数上不同的函数模板。这是非法的,因为默认模板参数不是函数模板签名的一部分,并且用相同的签名声明两个不同的函数模板是非法的。 所以看起来是这样的。但是,我看不出与前两个函数有太大的不同,前两个函数也有默认的模板参数。因此,我们对默认值(test1-work

  • 问题内容: 使用Hibernate的条件,我想执行以下操作: 我认为执行以下操作将产生想要的结果: 但是,这实际上是执行类似以下操作: 显然,这引发了错误。 除了不使用条件以外,还有解决方案吗? 谢谢, 布兰登 问题答案:

  • 问题内容: 这是我无法弄清楚的非常基本的查询。 假设我有一个两列的表格,如下所示: 我想获取所有具有1、2和3的不同用户ID 。使用上面的示例,我要返回的唯一结果是1。我该怎么做? 问题答案: 任何人阅读本:我的答案是简单明了的,并得到了“接受”的地位,但请不要去阅读答案通过@cletus给出。它具有更好的性能。 只是大声思考一下,@ cletus所描述的编写自联接的另一种方法是: 这对您来说可能