const 类型的 C++ 模板泛化
C++ template generalization for const type
我在这里做一个小研究,这需要在某个阶段,我有不同的 类 对某些数据进行(或不进行)操作,这取决于它的常量。
一个小例子是这样的(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;
};
但是无论如何,编译器没有找到它,并且仍然尝试编译非常量版本。
关于如何实现这一点有什么想法吗?
编译如果你改变:
template <class T>
class funny <T const>
至:
template <class T>
class funny <const T&>
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)
我在这里做一个小研究,这需要在某个阶段,我有不同的 类 对某些数据进行(或不进行)操作,这取决于它的常量。
一个小例子是这样的(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;
};
但是无论如何,编译器没有找到它,并且仍然尝试编译非常量版本。
关于如何实现这一点有什么想法吗?
编译如果你改变:
template <class T>
class funny <T const>
至:
template <class T>
class funny <const T&>
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)