Reputation: 26409
The following code compiles and works on G++ 4.4.0 and MS VC2008 Express.
#include <iostream>
template<typename T> struct A{
protected:
T v;
public:
const T get() const{
return v;
}
A(T v_)
:v(v_){
}
};
class B: public A<const int*>{
public:
void doSomething() const{
const int* tmp = get();
std::cout << *tmp << std::endl;
}
B(const int* p)
:A<const int*>(p){
}
};
int main(int argc, char** argv){
int a = 134;
B b(&a);
const B& c = b;
b.doSomething();
c.doSomething();
return 0;
}
However, as I understand it using A<const int*>
should result in const const int* A::get() const;
. And I'm pretty sure I haven't seen anything like that in real code. Is using template in such way "legal"?
If not, what are alternatives? In my code I need a template class that provides two "getter" methods (const/non-const), and can take a "const int*" as a type. Something like this:
template<typename T> struct A{
protected:
T v;
public:
const T get() const{
return v;
}
T get(){
return v;
}
A(T v_)
:v(v_){
}
};
Any ideas?
Upvotes: 5
Views: 1701
Reputation: 299740
It is not an issue to have multiple const
qualifiers: they just fold together.
However you are misinterpreting it, because you are not placing it correctly (and it's a shame the syntax allows it).
If you place the const
after the type it qualifies you'll realize that you were reading it wrong.
A const T
where T
is const int*
is NOT const const int* = const int*
.
If you write it correctly: T const
where T
is int const*
, then you will read it int const* const
, which is a const
pointer to a const
int, and NOT a pointer to a const
int.
Upvotes: 4
Reputation: 33655
All the other answers stand about constness, if you wanted the unqualified type, you can use a little template skull-duggery..
template <typename T>
struct remove_const
{
typedef T type;
};
template <typename T>
struct remove_const<T*>
{
typedef T* type;
};
template <typename T>
struct remove_const<const T>
{
typedef T type;
};
template <typename T>
struct remove_const<const T*>
{
typedef T* type;
};
template <typename T>
void foo (T& b)
{
typename remove_const<T>::type a = b;
}
If you pass in a const
pointer to foo
, you'll see that a
has the non-const type and therefore the assignment fails.
Upvotes: 1
Reputation: 38533
const int const *
is legal code and means a constant pointer to a constant value. Your code probably translates to the same expression.
Upvotes: 0
Reputation: 33385
It's fine to do this
struct Foo {};
typedef const Foo CFoo;
const CFoo c;
Upvotes: 2
Reputation: 9179
We can translate
const int *
into
int const *
A pointer to a constant int. When you have T=int*, what you have with const T is:
int * const
Which means, a constant pointer to a int.
So in your case with T=const int*, which is int const *, what you have with const T is:
int const * const
Which means a constant pointer to a constant int. Which is legal.
If it is not the desired behavior, you may have partial specialization, like:
template<typename T> struct A<const T>{
//here comes different implementation for the case where A template is
//initialized with a const type.
Upvotes: 4