C++ 指针作为模板参数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1134283/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
pointers as template parameters?
提问by D Garcia
I have a container class, we'll call it
我有一个容器类,我们称之为
template <class T> CVector { ... }
I want to do something different with this class when T is a pointer type, e.g. something along the lines of:
当 T 是指针类型时,我想对这个类做一些不同的事情,例如:
template <class T*> CVector< SomeWrapperClass<T> >;
where SomeWrapperClass is expecting the type of the pointed to thing as its parameter. Unfortunately, this syntax doesn't quite work and with some digging, I haven't found a good way to get something like this working.
其中 SomeWrapperClass 期望指向事物的类型作为其参数。不幸的是,这种语法并不完全有效,经过一些挖掘,我还没有找到一种很好的方法来使这样的事情工作。
Why do it this way? I want to change, in a very large app, how some of our containers work when the type they're specialized on is a pointer vs. not a pointer - and ideally, i'd like to do it without changing the ~1,000 places in the code where there are things like CVector<Object*>
vs CVector<int>
or some such - and playing games with partial specializations seemed to be the way to go.
为什么要这样做?我想在一个非常大的应用程序中改变我们的一些容器在它们专门处理的类型是指针而不是指针时的工作方式 - 理想情况下,我希望在不更改约 1,000 个位置的情况下进行在代码中存在诸如CVector<Object*>
vs 之类的东西CVector<int>
- 并且玩具有部分专业化的游戏似乎是要走的路。
Am I on crack here?
我在这里崩溃了吗?
回答by sth
If I understand you correctly, this might do what you want:
如果我理解正确,这可能会做你想要的:
template<typename T>
class CVector { ... };
template<typename T>
class CVector<T*> : public CVector< SomeWrapperClass<T> > {
public:
// for all constructors:
CVector(...) : CVector< SomeWrapperClass<T> >(...) {
}
};
It adds an additional layer of inheritance to trick CVector<T*>
into being a CVector< SomeWrapperClass<T> >
. This might also be useful in case you need to add additional methods to ensure full compatibility between the expected interface for T*
and the provided interface for SomeWrapperClass<T>
.
它添加了一个额外的继承层来欺骗CVector<T*>
成为一个CVector< SomeWrapperClass<T> >
. 如果您需要添加其他方法以确保预期的接口T*
和提供的接口之间的完全兼容性,这也可能很有用SomeWrapperClass<T>
。
回答by rlbond
This works just fine in C++...
这在 C++ 中工作得很好......
#include <iostream>
template <class T>
class CVector
{
public:
void test() { std::cout << "Not wrapped!\n"; }
};
template <class T>
class CVector<T*>
{
public:
void test() { std::cout << "Wrapped!\n"; }
};
int main()
{
CVector<int> i;
CVector<double> d;
CVector<int*> pi;
CVector<double*> pd;
i.test();
d.test();
pi.test();
pd.test();
}
回答by rmeador
I don't think you can specialize a class using the syntax you describe... I don't know how that could possibly work. What you can do is specialize the class for pointers and re-implement its guts using the wrapper class around the raw pointers. I'm not sure if it will help, but this articledescribes specializing templates for pointers.
我不认为你可以使用你描述的语法专门化一个类......我不知道这可能如何工作。您可以做的是将类专门化为指针,并使用原始指针周围的包装类重新实现其内部结构。我不确定它是否会有所帮助,但本文描述了专门的指针模板。
回答by Kristian
The Boost type traits librarycan help you achieve this. Check out the is_pointertype trait.
该升压型特征库可以帮助您实现这一目标。查看is_pointer类型特征。
#include <boost/type_traits.hpp>
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class CVector {
public:
void addValue(const T& t) {
values_.push_back(t);
}
void print() {
typedef boost::integral_constant<bool,
::boost::is_pointer<T>::value> truth_type;
for (unsigned int i = 0; i < values_.size(); i++)
doPrint(values_[i], truth_type());
}
private:
void doPrint(const T& t, const boost::false_type&) {
cout << "Not pointer. Value:" << t << endl;
}
void doPrint(const T& t, const boost::true_type&) {
cout << "Pointer. Value: " << *t << endl;
}
std::vector<T> values_;
};
int main() {
CVector<int> integers;
integers.addValue(3);
integers.addValue(5);
integers.print();
CVector<int*> pointers;
int three = 3;
int five = 5;
pointers.addValue(&three);
pointers.addValue(&five);
pointers.print();
}
回答by Glenn Yu
I agree with rlbond's answer. I have modified it a little bit to suit your need. CVector can be a derived class of the CVector itself. You can then use different members and functions for it.
我同意 rlbond 的回答。我对它进行了一些修改以满足您的需要。CVector 可以是 CVector 本身的派生类。然后,您可以为它使用不同的成员和函数。
#include <iostream>
#include <string>
template <class T>
class CVector
{
public:
void test() { std::cout << "Not wrapped!\n"; }
void testParent() { std::cout << "Parent Called\n";}
};
template <class T>
class CVector<T*>:
public CVector<T>
{
public:
void test(std::string msg) { std::cout << msg; testParent(); }
};
int main()
{
CVector<int> i;
CVector<double> d;
CVector<int*> pi;
CVector<double*> pd;
i.test();
d.test();
pi.test("Hello\n");
pd.test("World\n");
system("pause");
}
回答by Jesse Vogt
I don't think templates are quite that flexible.
我认为模板没有那么灵活。
A very brute force approach would be to specialize for all of your pointer types...which defeats the problem of using templates.
一种非常强力的方法是专门针对所有指针类型……这可以解决使用模板的问题。
Could you have a different CVector class that is used only for vectors of pointers?
你能有一个不同的 CVector 类只用于指针向量吗?