将const指针参数传递给模板类的成员函数

时间:2015-07-14 21:58:22

标签: c++ templates

考虑以下课程:

template<typename T> class A{
public:
    virtual void foo(const T& v){ m_v = v + 1; }    
    T& bar(){ return m_v;}
    T m_v;
    // ... other member functions/variables ...
};

如何修改以便以下代码有效(如果可能,则不需要const_cast上的p):

int main(){
    A<int*> a;
    const int* p = nullptr;
    a.foo(p);
    a.bar();

    A<int>().foo(10);
}

问题在于foo方法的签名,Aint*模板化后,就我所知,foo(int* const&)。我们希望拥有的内容类似于foo(const int* const&)

到目前为止,我考虑为类声明之外的指针类型添加foo成员函数的A成员函数的专门实现(如专门用于A<int>::foo),但是编译器无法将函数定义原型解析为声明的方法。

template<typename T>
void A<T*>::foo(const T* const& ){}

gcc抱怨它是invalid use of incomplete type ‘class A<T*>’

我还考虑为指针类型添加整个类的部分特化,它定义了一个额外的成员重载foo,它接收const T*,但我无法理解如何重用基本模板中的其余代码(即不重复所有其他函数的声明和定义,例如bar)。有没有办法从指针部分特化引用基本模板类,用于继承还是有一个转发调用的成员? (This post通过添加额外的虚拟模板参数来提供解决方案。有没有办法绕过这个?)。

最后,当模板参数是指针时,我还考虑过使用enable_if<is_pointer<T>::value, void>::type foo(const PointedToType*);foo方法添加额外的重载,但是如何才能获得PointedToType来自T(当知道T是指针类型时)?

3 个答案:

答案 0 :(得分:3)

对我来说,你只需要一个特征template <typename T> struct arg_type { using type = T const&; }; template <typename T> struct arg_type<T*> { using type = T const*; }; template <typename T> using arg_type_t = typename arg_type<T>::type; 的参数类型:

virtual void foo(arg_type_t<T> arg ) {}

如此使用:

{{1}}

答案 1 :(得分:1)

我不确定这是否是你想要的,但你可以使用std::is_pointerstd::remove_pointerstd::conditional的组合来构建你想要的参数类型。但是,我不知道如何编写函数体来对该参数做有用的事情。

#include <type_traits>

template <typename T>
struct A
{
  template <
    typename U = T,
    typename ArgT = std::conditional_t<
      std::is_pointer<U>::value,
      const std::remove_pointer_t<U> *,
      U>
  >
  void
  foo(const ArgT&)
  {
    // ...
  }
};

我在这里使用C ++ 14类型的元函数。如果您无法使用C ++ 14,请将std::fancy_t< … >替换为typename std::fancy< … >::type

以下内容现在有效:

int
main()
{
  {
    A<int *> a {};
    const int * p {};
    a.foo(p);
  }
  {
    A<int> a {};
    const int i {};
    a.foo(i);
  }
}

答案 2 :(得分:0)

您可以使用a模板参数定义const,即A<const int*> a;。那会有用。

template<typename T> class A{
public:
    void foo(const T &v){ m = v; }
    void bar(T &v){ v = m; }
    T m;
    // ... other member functions/variables ...
};

int main(){
    A<const int*> a;
    const int* p = nullptr;
    a.foo(p);
    a.bar(p);
}