[英]Passing a const pointer argument to a member function of a template class
Consider the following class: 考虑以下类别:
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 ...
};
How can it be modified such that the following code works (without, if possible having to to a const_cast
on p
): 它如何能够被修改,使得下面的代码工作(无,如果可能的话具有向一个
const_cast
上p
):
int main(){
A<int*> a;
const int* p = nullptr;
a.foo(p);
a.bar();
A<int>().foo(10);
}
The problem is that the signature of the foo
method, when A
is templated by int*
becomes, as far as I can tell, foo(int* const&)
. 问题是,据我所知,当
A
由int*
模板化时, foo
方法的签名变成foo(int* const&)
。 What we would like to have would be something like foo(const int* const&)
. 我们想拥有的东西应该像
foo(const int* const&)
。
Until now, I considered adding a specialized implementation of the foo
member function for A
templated by pointer types outside the class declaration (as one would do for specializing A<int>::foo
), but the compiler is not able to resolve the function definition prototype to the declared method. 到目前为止,我考虑过为
A
成员添加一个foo
成员函数的专门实现,该实现由类声明之外的指针类型进行模板化(就像对A<int>::foo
进行专门化那样),但是编译器无法解析该函数定义原型到声明的方法。
template<typename T>
void A<T*>::foo(const T* const& ){}
gcc complains that it's an invalid use of incomplete type 'class A<T*>'
gcc抱怨这是
invalid use of incomplete type 'class A<T*>'
的invalid use of incomplete type 'class A<T*>'
I've also considered adding a partial specialization for the whole class for pointer types which defines an extra member overloading foo
that takes in a const T*
, but I couldn't figure out how to reuse the rest of the code in the base template (ie without duplicating the declarations and definitions for all the other functions, eg bar
). 我还考虑过为指针类型的整个类添加部分专门化,它定义了一个额外的成员重载
foo
,该foo
接受const T*
,但是我不知道如何重用基本模板中的其余代码(即,不重复所有其他函数的声明和定义,例如bar
)。 Is there a way to reference the base template class from the pointer partial specialization, either for inheritance or for having a member to which to forward calls? 有没有一种方法可以从指针局部特化中引用基本模板类,以进行继承或具有将调用转发到的成员? ( This post provides a solution by adding an extra dummy template argument. Is there a way to circumvent this?).
( 这篇文章提供了通过增加一个额外的虚拟模板参数的解决方案。有没有办法来规避呢?)。
Finally, I've also thought about using enable_if<is_pointer<T>::value, void>::type foo(const PointedToType*);
最后,我还考虑过使用
enable_if<is_pointer<T>::value, void>::type foo(const PointedToType*);
to add an extra overload to the foo
method when the template parameter is a pointer, but how can one get PointedToType
from T
(when it is known that T
is a pointer type)? 当模板参数是指针时,如何在
foo
方法中添加额外的重载,但是如何从T
获取PointedToType
(当已知T
是指针类型时)?
Seems to me that you just need a trait for what the argument type of foo
should be: 在我看来,您只需要为
foo
的参数类型指定一个特征即可:
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;
To be used thusly: 因此使用:
virtual void foo(arg_type_t<T> arg ) {}
I'm not sure if this is what you want but you could use a combination of std::is_pointer
, std::remove_pointer
and std::conditional
to construct the argument type you want. 我不确定这是否是您想要的,但是您可以结合使用
std::is_pointer
, std::remove_pointer
和std::conditional
来构造所需的参数类型。 I don't know how you would write the function body to do useful things with that argument, however. 但是,我不知道您将如何编写函数主体以使用该参数来执行有用的操作。
#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&)
{
// ...
}
};
I'm using the C++14 type meta-functions here. 我在这里使用C ++ 14类型的元函数。 If you cannot use C++14, replace
std::fancy_t< … >
with typename std::fancy< … >::type
. 如果您不能使用C ++ 14,
std::fancy_t< … >
替换为typename std::fancy< … >::type
。
The following is now valid: 现在有效:
int
main()
{
{
A<int *> a {};
const int * p {};
a.foo(p);
}
{
A<int> a {};
const int i {};
a.foo(i);
}
}
You could just define a
with a const
template argument, ie, A<const int*> a;
您可以使用
const
模板参数定义a
,即A<const int*> a;
. 。 That would work.
那行得通。
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.