SigTerm
SigTerm

Reputation: 26409

"const const T" in template

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

Answers (6)

Matthieu M.
Matthieu M.

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

Nim
Nim

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

mihai
mihai

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

spraff
spraff

Reputation: 33385

It's fine to do this

struct Foo {};
typedef const Foo CFoo;

const CFoo c;

Upvotes: 2

Andr&#233; Puel
Andr&#233; Puel

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

Kerrek SB
Kerrek SB

Reputation: 476950

If T = const int *, then const T is const int * const.

Upvotes: 5

Related Questions