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

std::enable_if:参数vs模板参数

齐昊苍
2023-03-14

我正在构建一些输入检查器,需要为整数和/或双精度设置特定的函数(例如,“iPrime”应该只适用于整数)。

如果我使用enable_If作为参数,它工作得很好:

template <class T>
class check
{
public:
   template< class U = T>
   inline static U readVal(typename std::enable_if<std::is_same<U, int>::value >::type* = 0)
   {
      return BuffCheck.getInt();
   }

   template< class U = T>
   inline static U readVal(typename std::enable_if<std::is_same<U, double>::value >::type* = 0)
   {
      return BuffCheck.getDouble();
   }   
};

但如果我将其用作模板参数(如上所示)http://en.cppreference.com/w/cpp/types/enable_if )

template <class T>
class check
{
public:
   template< class U = T, class = typename std::enable_if<std::is_same<U, int>::value>::type >
   inline static U readVal()
   {
      return BuffCheck.getInt();
   }

   template< class U = T, class = typename std::enable_if<std::is_same<U, double>::value>::type >
   inline static U readVal()
   {
      return BuffCheck.getDouble();
   }
};

那么我有以下错误:

error: ‘template<class T> template<class U, class> static U check::readVal()’ cannot be overloaded
error: with ‘template<class T> template<class U, class> static U check::readVal()’

我不知道第二个版本出了什么问题。

共有3个答案

薛鹏飞
2023-03-14

我知道这个问题是关于std::enable_if,但是,我想提供一个替代解决方案,在不启用_if的情况下解决相同的问题。它确实需要C17

template <class T>
class check
{
public:
   inline static T readVal()
   {
        if constexpr (std::is_same_v<T, int>)
             return BuffCheck.getInt();
        else if constexpr (std::is_same_v<T, double>)
             return BuffCheck.getDouble();
   }   
};

这段代码看起来更像是在运行时编写的。所有分支都必须是语法正确的,但语义不一定是正确的。在这种情况下,如果T是int,getDouble不会导致编译错误(或警告),因为编译器不会检查/使用它。

如果函数的返回类型非常复杂,则始终可以使用auto作为返回类型。

方嘉言
2023-03-14

问题是编译器会看到同一方法的两个重载,它们都包含相同的参数(本例中为none)和相同的返回值。你不能给出这样的定义。最干净的方法是在函数的返回值上使用SFINAE:

template <class T>
class check
{
public:
   template< class U = T>
   static typename std::enable_if<std::is_same<U, int>::value, U>::type readVal()
   {
      return BuffCheck.getInt();
   }

   template< class U = T>
   static typename std::enable_if<std::is_same<U, double>::value, U>::type readVal()
   {
      return BuffCheck.getDouble();
   }
};

这样,您就提供了两种不同的重载。一个返回int,另一个返回双精度,并且只能使用特定的T实例化一个。

吕昀
2023-03-14

默认模板参数不是模板签名的一部分(因此两个定义都尝试两次定义相同的模板)。但是,它们的参数类型是签名的一部分。所以你可以这样做

template <class T>
class check
{
public:
   template< class U = T, 
             typename std::enable_if<std::is_same<U, int>::value, int>::type = 0>
   inline static U readVal()
   {
      return BuffCheck.getInt();
   }

   template< class U = T, 
             typename std::enable_if<std::is_same<U, double>::value, int>::type = 0>
   inline static U readVal()
   {
      return BuffCheck.getDouble();
   }
};
 类似资料:
  • 我目前有一个,但是为了灵活性,我希望能够分配一个lambda表达式,将作为映射中的值返回。 所以我创建了这个模板类: 并像这样使用它: IntelliSense提供了更多信息: 多个操作符“=”匹配这些操作数:function“valueorfunction::operator=(const std::function&other)[with T=std::wstring]”function“va

  • 假设有一个模板函数 接受任意数量的参数。给定最后一个参数始终是 ,我如何实现下面显示的 模板,以便 包含此 的参数? 例如,如果像这样调用,应该是: 我的第一个想法是: 但这不会编译: 问题一: 为什么这不能编译?为什么模板参数演绎失败? 最终,我想出了这个解决方案: 这里,是,即中的最后一种类型。然后,的临时值被传递到,其中。这行得通,但在我看来很难看。 问题二: 我想知道如果没有两个函数和的临

  • 如果我没有理解错的话,类模板定义了一个函数,所以当我调用时,编译器有可能进行隐式强制转换,但是在函数模板的情况下,此时没有函数定义,所以隐式强制转换不会发生。 但我不明白为什么编译器不能创建函数定义,然后应用隐式强制转换? 错误是: 在函数“int main()”中:    25:24:错误:调用“test2::add(void(&)(int))”没有匹配函数    25:24:注:候选人是:  

  • 我有一个下面的类模板 给出以下错误: tmp.cc:19:27:错误:无法专门化(使用“template<>”)未专门化模板constexpr int MyClass::ArraySize<0>()的成员{return 0;} 有可能达到预期的行为吗?使用C++14/C++17特性的解决方案(我想如果-constexpr应该是可能的)受到欢迎,但不能解决我的特定问题,因为只有C++11可用。

  • Stroustrup C++第4版第796页指出 “如果的条件计算为,则完全忽略它所在的整个函数声明。”和“...我们不申报任何东西。”。 我也读过这个建议的线程,在这个线程中,SFINAE只有在模板参数的参数推导中的替换使构造格式不正确时才起作用。

  • 我希望维护语法,但似乎只能将typenames放在括号中,而不能将类放在括号中。以下是我当前的代码: 问题1:我找不到一种方法来使“default”参数对于特殊化不是必需的。我尝试了使用默认构造函数的代理类,将第三个参数更改为指针,并指定nullptr(这在语法上并不理想)和对类型的常量引用(这仍然需要用户端的三个参数),但似乎没有任何东西允许在中接受两个参数。 问题2:我找不到正确的语法来获得混