【问题标题】:C++ enable_if in class - different ways of destruction类中的 C++ enable_if - 不同的破坏方式
【发布时间】:2016-04-14 19:59:48
【问题描述】:

我正在为嵌入式设备开发应用程序,因此我没有type_traitsenable_if(编译器质量差)。我自己创建了它们:

template <typename T>
struct is_pointer_t{
    enum{value = false};
};

template <typename T>
struct is_pointer_t<T*>{
    enum{value = true};
};

以及constsvolatiles 的类似声明。

现在实现enable_if

template <bool boolean, typename T = void>
struct enable_if{};

template <typename T>
struct enable_if<true, T>{
    typedef T type;
};

现在我想要一个类,取决于我是否使用指针或普通类型,它是否在它们上调用析构函数,所以如果我可以有模板化析构函数会很棒。但是我不知道该怎么做,因为我刚刚开始不了解模板编程。以下尝试失败:

template <typename T>
class pointerOrNot{
public:

    template <typename U>
    void one();
};

template <typename T>
template <typename enable_if<is_pointer_t<T>::value>::type>
void pointerOrNot<T>::one(){
    std::cout << "Success1" << std::endl;
}

template <typename T>
template <typename enable_if<!is_pointer_t<T>::value>::type>
void pointerOrNot<T>::one(){
    std::cout << "Success2" << std::endl;
}

它说它与定义不匹配。所以我尝试了以下操作:

template <typename T>
class pointerOrNot{
public:

    template <typename enable_if<is_pointer_t<T>::value>::type>
    void one();
    template <typename enable_if<!is_pointer_t<T>::value>::type>
    void one();
};

但是 one() 之一的模板类型为空,编译失败。我怎样才能做到这一点?也可以用析构函数来做到这一点吗?

【问题讨论】:

  • 由于所有权问题,我根本不会接受任何原始指针,而不是选择销毁策略。您仍然可以使用包装在智能指针对象中的原始指针,无论是否进行销毁,作为客户端代码选择。定义智能指针并不难,这是完全分离关注点的一种好方法。
  • 如果你真的想选择指针类型还是非指针类型,那么你可以使用专门用于 is 和 is-not 的辅助函数模板。您还可以使用所谓的“基于策略的设计”,它本质上是关于将模板 P 作为模板参数,其中 P 由例如实例化。您的 T 并提供例如销毁操作。但是您可以通过智能指针获得更简单、更清晰的关注点分离。
  • 在我的拙见中,比enable_if 更具可读性的替代品,我称之为If_,请参阅(github.com/alf-p-steinbach/cppx/blob/plutonium/…)。

标签: c++ templates destructor


【解决方案1】:

首先让我们考虑以下指针类:

template <typename T>
struct Introducer{

  void intro(){
    std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
  }

  T mem;
  Introducer(T m):mem(m){}
};

它适用于指针,但它也适用于非指针:

  Introducer<int> i(10);
  i.intro();//just fine!

我们想在编译时检测到这种滥用,我们也将 Introducer 更改为

template <typename T>
struct Introducer{

  typename enable_if<is_pointer_t<T>::value, void>::type //this is the return type of the function
  intro(){
    std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
  }

  ...
};

现在编译器不允许我们在 Introducer 中使用非指针。在下一步中,我们希望通过SFINAE 为非指针提供一个特殊功能:

template <typename T>
struct Introducer{
  typename enable_if<is_pointer_t<T>::value, void>::type 
  intro(){
    std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
  }

  typename enable_if<!is_pointer_t<T>::value, void>::type 
  intro(){
    std::cout<<"I'm a non-pointer, my value is "<<mem<<std::endl;
  }

  ...
};

见鬼,它甚至无法编译!让我们更仔细地阅读有关 SFINAE 的文章:

如果替换导致无效的类型或表达式,请键入 扣除失败。无效的类型或表达式是 如果使用替换的参数编写,则格式错误。仅无效 类型和表达式在函数类型的直接上下文中 其模板参数类型可能会导致推演失败。

T 不在直接上下文中,因此 SFINAE 不起作用,让我们将 T 带入直接上下文中:

template <typename T>
struct Introducer{

  template <typename C=T>
  typename enable_if<is_pointer_t<C>::value, void>::type 
  intro(){
    std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl;
  }


  template <typename C=T>
  typename enable_if<!is_pointer_t<C>::value, void>::type 
  intro(){
    std::cout<<"I'm a non-pointer, my value is "<<mem<<std::endl;
  }

  ...
};

现在是程序

int main(){
  Introducer<float*> fp(NULL);
  fp.intro();

  //But this works also:
  Introducer<int> i(10);
  i.intro();
}

结果:

I'm a pointer, I point to adress 0
I'm a non-pointer, my value is 10

析构函数呢?最简单的方法是从析构函数中调用 SFINAE 析构函数(我从未见过 SFINAE 析构函数,也不知道如何编写,但这没有任何意义):

template <typename T>
struct Introducer{
  ...

    ~Introducer(){
    intro();
    std::cout<<"and I'm deleted..."<<std::endl;
  }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-22
    • 2011-06-11
    • 1970-01-01
    • 2012-03-03
    • 2016-02-08
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多