如何为所有引用类型专门化类
How to specialize classes for all reference types C++03
请注意c++ 03是我真正需要的,但为了知识起见,我希望在c++ 11中看到一些更漂亮的实现。
我需要一个模板类template <typename T>
class A {
private:
T m_member;
public:
A(T _member);
//... MORE STUFF
void foo(T param);
};
我需要:
1)如果A是用值类型编译的(包括指针,指针本身是通过值传递的):
然后我需要A看起来像这样(完全像上面)
class A {
private:
T m_member;
public:
A(T _member);
//... MORE STUFF
void foo(T param);
};
2)如果A使用引用类型(例如int&
)编译:
然后我需要A看起来像这样:
class A{
private:
T& m_member;
public:
A(T& _member);
//... MORE STUFF
void foo(T param); // still the same T, not T&
};
如果我知道A只接收int型,那么我就可以使用专门化。但是A的用户可以使用任何类型:
main.cpp
A<int> a1;//1st version
A<int&> a2;//2nd version
A<B> a3;//1st version
A<B&> a4;//2nd version
A<C*> a5;//1st version
在这个线程专门化函数模板中可以看到(正确地),这里建议的remove_reference不起作用。它只是永远不会进入第二次实现,因为编译器看到了T&和T是一样的
相反,你可以手动告诉编译器它现在正在处理引用类型,使用相同的专门化技巧
template<typename T, bool isReference>
class A {
};
template<typename T>
class A<T,false>{
private:
T m_member;
public:
A(T _member);
//... MORE STUFF
void foo(T param);
}
/////////////////////////
template<typename T>
class A<T,true>{
private:
T& m_member;
public:
A(T& _member);
//... MORE STUFF
void foo(T param);
}
如果您想提取一些类似的行为并避免此解决方案导致的代码重复,您可以轻松地将该行为提取到Base Class<T>
,并执行
template<typename T,bool isReference>
class A : public BaseClass<T>{
}
等等
用法为
main.cpp
A<int,false> a1;//1st version
A<int&,true> a2;//2nd version
A<B,false> a3;//1st version
A<B&,true> a4;//2nd version
A<C*,false> a5;//1st version, as pointers are value types
注意:这个答案的想法归功于n.m.
要使您的想法工作,您只需要使foo
的函数参数类型始终为非引用类型。在c++ 11中有一个名为std::remove_reference
的辅助函数模板,但在c++ 03中可以很容易地实现。示例代码:
#include <iostream>
template<typename T> struct remove_reference {typedef T type;};
template<typename T> struct remove_reference<T&> {typedef T type;};
template<typename T>
class A{
private:
T m_member;
public:
A(T m): m_member(m) {}
void foo(typename remove_reference<T>::type param) { param = 0; }
};
struct B { int x; B(int x): x(x) {} };
struct C {};
int main()
{
int a = 1;
A<int> a1(a);
A<int&> a2(a);
a1.foo(a); std::cout << a << std::endl;
a2.foo(a); std::cout << a << std::endl;
B b(1);
A<B> b1(b);
A<B&> b2(b);
b1.foo(b); std::cout << b.x << std::endl;
b2.foo(b); std::cout << b.x << std::endl;
C c;
A<C*> c1(&c);
c1.foo(&c);
}
输出:$ g++ -o r r.cc -std=c++03 && ./r
1
1
1
1
可以看到,1
的输出表明参数是通过value传递的(因此param = 0
改变的是一个本地副本,而不是作为参数给出的对象)。
foo
中输出gcc扩展__PRETTY_FUNCTION__
。调用a2.foo(a);
的那一行的输出是:
void A<T>::foo(typename remove_reference<T>::type) [with T = int&; typename remove_reference<T>::type = int]
相关文章:
- 强制转换为引用类型
- 自定义引用类型
- Java 中是否有类似于 C++ 中引用类型"&"的内容?
- 为什么我不能在运算符=中使用引用类型?
- 可变参数模板函数参数和引用类型推导
- 隐式可转换参数,但属于引用类型
- 如何告诉自动推断向量<bool>元素的非引用类型
- 为什么"const auto [x, y]"绑定到引用类型时没有按预期运行?
- 引用类型的数据成员提供有关恒常正确性"loophole"
- 为什么引用类型在使用临时对象访问时是左值
- 什么是常量指针常量引用类型的参数?(const X* const & p)
- 在 lambda 中从引用类型捕获的值的类型,不使用通用捕获
- 如果类在 C++ 中具有常量或引用类型的非静态数据成员,为什么编译器不提供默认赋值运算符?
- void*作为通用引用类型是如何工作的
- 强制转换为不相关的引用类型是否违反严格的别名规则?
- C++ 引用类型作为递归函数参数
- EXPECT_CALL具有 unique_ptr 引用类型参数的模拟函数
- 如果使用返回引用的函数初始化"auto"var,为什么它不声明引用类型?
- 为什么模板引用类型不能用作模板类型别名参数?
- 如何为所有引用类型专门化类