【问题标题】:Have a template parameter that can be pointer type or non-pointer type有一个可以是指针类型或非指针类型的模板参数
【发布时间】:2016-08-23 09:41:25
【问题描述】:

假设我有类似的东西:

template <class T>
void do_something(T t){
  pass_it_somewhere(t);
  t->do_something();
}

现在允许T 是指针或非指针类型会很有用。函数do_something(...)基本上可以处理指针和非指针,除了t-&gt;do_something()。对于指针,我需要一个-&gt;,对于非指针,我需要一个. 来访问成员。

有没有办法让T 接受指针非指针?

【问题讨论】:

标签: c++ templates pointers c++11


【解决方案1】:

您可以创建如下的取消引用机制:

template<typename T>
std::enable_if_t<std::is_pointer<T>::value, std::remove_pointer_t<T>&> dereference(T& t) { 
  return *t; 
}

template<typename T>
std::enable_if_t<!std::is_pointer<T>::value, T&> dereference(T& t) {
  return t;
}

并在你的函数中使用它:

template <class T>
void do_something(T t){
  pass_it_somewhere(dereference(t));
  dereference(t).do_something();
}

Live Demo

这样你只需要处理T 的具体版本。

【讨论】:

  • 我认为这是最好的答案,因为它会产生非常可读和简洁的代码。谢谢:-)
【解决方案2】:

灵魂 1

使用模板特化:

template <class T>
void do_something(T t){
  pass_it_somewhere(t);
  t.do_something();
}

template <class T>
void do_something(T* t){
  pass_it_somewhere(t);    
  t->do_something();
}

解决方案 2

在类 T 中添加一个用户定义的指针操作符:

class A
{
public:
    void do_something() const {}        
    const A* operator->() const { return this; }
};

template <class T>
void do_something(T t){
  pass_it_somewhere(t);      
  t->do_something();
}

【讨论】:

  • s/specialize/overload
【解决方案3】:

另一个解决方案:标签调度。

namespace detail {
    struct tag_value {};
    struct tag_ptr {};

    template <bool T>  struct dispatch       { using type = tag_value; };
    template <>        struct dispatch<true> { using type = tag_ptr;   };

    template <class T>
    void do_call(T v, tag_value)
    {
      v.call();
    }

    template <class T>
    void do_call(T ptr, tag_ptr)
    {
       ptr->call();
    }
}

那么你的函数就变成了:

template <class T>
void do_something(T unknown)
{
   do_call(unknown, 
                typename detail::dispatch<std::is_pointer<T>::value>::type{} );

   // found by ADL

}

Live Example.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    相关资源
    最近更新 更多