const类型的C++模板泛化
我在这里做了一个小型的研究,这需要在某个阶段,我有不同的类在某些数据上做(或不做)操作,这取决于它的常量。const类型的C++模板泛化
一个小例子是这样的(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版本。
有关如何实现此目的的任何想法?
编译如果你改变:
template <class T>
class funny <T const>
到:
template <class T>
class funny <const T&>
确实如此:)谢谢! – fritzone
请注意,这是因为'decltype(t [0])'是一个参考。这对于一些'const char'不起作用。 @Miles的答案更强大。 – TartanLlama
@TartanLlama我同意 – marcinj
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)
正如你可以在错误信息,'T'被推断为'为const char&',这是一个参考,请参阅type,因此不是const限定的('T'是'X&',其中'X'是'const char')。这是因为't [0]'是一个表达式和一个表达式,是一个左值。这种表达式的decltype(e)产生一个左值参考类型。 – dyp