const类型的C ++模板泛化

时间:2016-08-12 10:32:55

标签: c++ templates const template-specialization

我在这里做了一个小小的研究,在某个阶段,我需要不同的类对某些数据进行(或不做)操作,具体取决于它的常量。

一个小例子就是这样(http://coliru.stacked-crooked.com/a/75c29cddbe6d8ef6

#include <iostream>

template <class T>
class funny
{
public:
    funny(T& a) : v(a) {v -= 1; }
    virtual ~funny() { v += 1; }
    operator T() {return v;}

private:
    T& v;
};

#define V(a) funny<decltype(a)>(a)

int main()
{
    char t[] = "ABC"; // <-- HERE

    if( V( t[0] ) == (char)'A')
    {
        std::cout << "Pass" << t[0];
    }
    else
    {
        std::cout << "No Pass" << t[0];
    }
}

现在,问题出现了:

如果我将标记为<-- HERE的行修改为

const char t[] = "ABC";

我收到以下编译错误:

main.cpp: In instantiation of 'funny<T>::funny(T&) [with T = const char&]':
main.cpp:21:7:   required from here
main.cpp:7:28: error: assignment of read-only location '((funny<const char&>*)this)->funny<const char&>::v'
  funny(T& a) : v(a) {v -= 1; }
                      ~~^~~~
main.cpp: In instantiation of 'funny<T>::~funny() [with T = const char&]':
main.cpp:21:7:   required from here
main.cpp:8:27: error: assignment of read-only location '((funny<const char&>*)this)->funny<const char&>::v'
  virtual ~funny() { v += 1; }
                     ~~^~~~

这是完全可以理解的,因为我尝试修改常量。编译器就在这里。但是,我真的需要这个也适用于const数据,所以我尝试创建模板的const特化:

template <class T>
class funny <T const>
{
public:
    funny(const T& a) : v(a) {}
    operator T() {return v;}

private:
    const T& v;
};

但无论如何,编译器都找不到它,仍然试图编译非const版本。

关于如何实现这一目标的任何想法?

2 个答案:

答案 0 :(得分:4)

decltype(t[0])推断为const char&,与您的const char专业化不匹配。您有两种选择:

1)将您的专业化更改为template <class T> class funny <T const&>。这适用于这种情况,但不适用于const int FOO = 42; V(FOO);

2)将您的V宏更改为始终推导为非引用类型:

#define V(a) funny<typename std::remove_reference<decltype(a)>::type>(a)

答案 1 :(得分:1)

如果更改则编译:

template <class T>
class funny <T const>

为:

template <class T>
class funny <const T&>