【问题标题】:`std::enable_if` SFINAE custom type via template parameter?`std::enable_if` SFINAE 通过模板参数自定义类型?
【发布时间】:2015-05-05 10:26:33
【问题描述】:

第一个问题:假设我有一个像这样的自定义struct

struct Var {};   

struct is_var_type: std::integral_constant<bool, std::is_same<Var, typename std::remove_cv<T>::type>::value> {};

在此之后,我想通过模板参数 SFINAE 使用std::enable_if 获得一些自定义类型,但是我无法弄清楚。我只能这样做:

template<typename T> 
void variant(T a)
{ 
    if (is_var_type<Var>::value){
        std::cout << " " << true;
    }
    else {
        std::cout << " " << false;  
    }
}

我想做这样的东西,但是std::is_integral 已经被定义了。如何定制?

template<class T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> // I couldn't figure out how to make custom integral_constant via template parameter 
T foo3(T t) // note, function signature is unmodified
{
    return t; //so this type should be an int, but I want to make sure that this type T is is_var_type struct, is this possible?
}

第二个问题:如果我们添加一些这样的容器类型,这种方式可能吗?

struct Var {};
struct ListVar: public std::list<Var>
struct is_var_type: std::integral_constant<bool, std::is_same<ListVar, typename std::remove_cv<T>::type>::value> {};

– 但我遇到了一个更令人困惑的编译时错误,例如无法在gcc 4.9 中推断出多个类型。

【问题讨论】:

  • 不应该is_var_type 是模板吗?
  • 我再次编辑了我的问题,以使其更清楚。
  • struct Var:{}; - 为什么是冒号?这不会编译。

标签: list c++11 templates std enable-if


【解决方案1】:

我会将is_var_type 设为包装std::is_same 的模板别名。解决方案可能如下所示。

#include <type_traits> // for std::decay
#include <iostream>

struct Var {};

// define is_var_type
template<class T>
using is_var_type = std::is_same<Var, typename std::decay<T>::type >;

// function that works for Var
template<class T
       , typename std::enable_if<is_var_type<T>::value>::type* = nullptr
       >
T foo3(T t)
{
   std::cout << " T is type Var " << std::endl;
   return t;
}

// function that works for int
template<class T
       , typename std::enable_if<std::is_same<T,int>::value>::type* = nullptr
       >
T foo3(T t)
{
   std::cout << " T is type int " << std::endl;
   return t;
}

int main()
{
   Var v;
   foo3(v); // calls foo3 for type Var

   int i;
   foo3(i); // calls foo3 for type int
   return 0;
}

您也可以像在示例中那样使用std::integral_constant 定义is_var_type(在定义之前您缺少template&lt;class T&gt;):

template<class T>
struct is_var_type:std::integral_constant<bool,std::is_same<Var,typename std::decay<T>::type>::value > 
{
};

编辑:

对于Var的容器,情况同上,现在我们只检查T是否属于ListVar类型:

// define structure that is a list of Var
struct ListVar : public std::list<Var>
{
};

// struct that checks whether T is a ListVar
template<class T>
struct is_list_of_var_type : std::integral_constant<bool,std::is_same<ListVar, typename  std::remove_cv<T>::type>::value > {};

// function that only works for ListVar
template<class T
       , typename std::enable_if<is_list_of_var_type<T>::value>::type* = nullptr
       >
T foo3(T t)
{
   std::cout << " T is type ListVar " << std::endl;
   return t;
}

// ... some code ...
ListVar lv;
foo3(lv); // call foo3 for ListVar

【讨论】:

  • 感谢您的回答,根据您的第二个问题,使用相同的用例但添加了容器类型,您知道吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-18
  • 2021-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多