Hmm a strange one in VC2012 I can't seem to work out the syntax for passing a const pointer by const reference into a function of a templated class whose template argument is a non const pointer ie:
template<typename T>
struct Foo
{
void Add( const T& Bar ) { printf(Bar); }
};
void main()
{
Foo<char*> foo;
const char* name = "FooBar";
foo.Add(name); // Causes error
}
So I've simplified my problem here but basically I want the argument to 'Add' to have a const T ie const char*. I've tried:
void Add( const (const T)& Bar );
typedef const T ConstT;
void Add( const (ConstT)& Bar );
void Add( const typename std::add_const<T>::type& Bar );
None of which work. The exact error I'm getting is:
error C2664: 'Foo<T>::Add' : cannot convert parameter 1 from 'const char *' to 'char *const &'
with
[
T=char *
]
Conversion loses qualifiers
which I can see is correct but how do I solve it without const casting 'name' to be non const.
There is a strong difference between a pointer to a constant object (T const*
, or const T*
) and a constant pointer to a non-constant object (T * const
). In your case the signature of the member Add
is:
void Foo<char *>::Add(char * const& ); // reference to a constant pointer to a
// non-constant char
I usually recommend that people drop the use of const
on the left hand side exactly for this reason, as beginners usually confuse typedef
s (or deduced types) with type substitution and when they read:
const T& [T == char*]
They misinterpret
const char*&
If the const
is placed in the right place:
T const &
Things are simpler for beginners, as plain mental substitution works:
char * const &
A different problem than what you are asking, but maybe what you think you want, is:
Given a type T
have a function that takes a U
that is const T
if T
is not a pointer type, or X const *
if T
is a pointer to X
template <typename T>
struct add_const_here_or_there {
typedef T const type;
};
template <typename T>
struct add_const_here_or_there<T*> {
typedef T const * type;
};
Then you can use this in your signature:
template <typename T>
void Foo<T>::Add( const typename add_const_here_or_there<T>::type & arg ) {
...
Note that I am adding two const
in the signature, so in your case char*
will map to char const * const &
, as it seems that you want to pass a const&
to something and you also want the pointed type to be const
.
You might have wondered as of the name for the metafunction: *add_const_here_or_there*, it is like that for a reason: there is no simple way of describing what you are trying to do, which is usually a code smell. But here you have your solution.
It looks like your issue here as that as soon as you have a pointer type mapped to a template type, you can no longer add const-ness to the pointed-to type, only to the pointer itself. What it looks like you're trying to do is automatically add constness to the parameter of your function (so if T is char*
the function should accept const char* const&
rather than char* const&
as you've written). The only way to do that is with another template to add constness to the pointee for pointer types, as follows. I took the liberty of including missing headers and correcting the signature of main
:
#include <cstdio>
template<typename T>
struct add_const_to_pointee
{
typedef T type;
};
template <typename T>
struct add_const_to_pointee<T*>
{
typedef const T* type;
};
template<typename T>
struct Foo
{
void Add( typename add_const_to_pointee<T>::type const & Bar ) { printf(Bar); }
};
int main()
{
Foo<char*> foo;
const char* name = "FooBar";
foo.Add(name); // Causes error
}
As mentioned in another another however, this issue just goes away if you use std::string
instead of C-style strings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With