const references in c++ templates

2020-06-01 03:23发布

In a C++ template with the generic type T, I can use

const T &

to get a reference to a constant T. However, if now T itself is a reference type (like e.g. T = int &), the above term resolves to

int &

and not to

const int &

which quite makes sense, since any reference itself is always constant. However, is there still a way to require a

const T &

if T itself is a reference type?

Edit: sample code to evaluate (g++ compiler):

template <typename T> class TemplateClass
{
public:
    void foo(const T &bar) { }
};

int main()
{
    TemplateClass<int &> x;
    x.foo(0);   // <-- compile error: no conversion from int to int&
    return 0;
}

3条回答
够拽才男人
2楼-- · 2020-06-01 03:50

You can always use template specialisation to implement a different version for any kind of reference:

template <typename T> struct X {
  void foo(T const&);
};

template <typename T> struct X<T&> {
  void foo(T const&);
};

Now, X<int>::foo expects an int const& and X<int&>::foo expects an int const&, too.

However, it is not entirely clear from your question what you are trying to do exactly.


Edit: My g++ version (4.6.1) does not complain without template specialisation for the following

int i = 7;
X<int&>(i);

While it does for

X<int&>(7);

Which is correct IMO, because you try to convert a temporary (7) to a mutable reference (even if that is a reference to a const reference).


Edit 2: If you want to reduce duplicate code, then do not specialise your original class, but use this:

template <typename T> struct R {
  typedef T& Ref;
  typedef T const& ConstRef;
};

template <typename T> struct R<T&> {
  typedef T& Ref;
  typedef T const& ConstRef;
};

template<typename T> struct X {
  void foo(typename R<T>::ConstRef x);
};
查看更多
你好瞎i
3楼-- · 2020-06-01 04:00

I have encountered the very same problem. It seems that the '&' type conversion operator binds stronger than the 'const' qualifier. So when we have this code:

template<class t>
void fun(const t i)
{
}

fun<int&>();

the function ends up with type void(int&), not the expected void(const int&).

To solve this problem, I have defined this template:

template<class t> struct constify { typedef t type; };
template<class t> struct constify<t&> { typedef const t& type; };

Now define your function as:

template<class t>
void fun(typename constify<t>::type i)
{
}

fun<int&>();

The instantiated function will have the type void(const int&), as needed.

查看更多
一夜七次
4楼-- · 2020-06-01 04:04

Remove the reference:

template<typename T>
void Test(const typename std::remove_reference<T>::type & param)
{
        param = 20;
}

Now it works as expected.

查看更多
登录 后发表回答