指针作为模板参数?

发布于 2024-07-29 01:18:15 字数 560 浏览 6 评论 0原文

我有一个容器类,我们称之为容器类,

template <class T> CVector { ... } 

当 T 是指针类型时,我想对这个类做一些不同的事情,例如:

template <class T*> CVector< SomeWrapperClass<T> >;

其中 SomeWrapperClass 期望将所指向事物的类型作为其参数。 不幸的是,这种语法不太有效,经过一番挖掘,我还没有找到一个好的方法来让这样的东西工作。

为什么要这样做呢? 我想改变,在一个非常大的应用程序中,当我们的一些容器专门处理的类型是指针而不是指针时,它们的工作方式 - 理想情况下,我想在不更改〜1,000个位置的情况下做到这一点在代码中,有诸如 CVector vs CVector 之类的东西 - 并且玩具有部分专业化的游戏似乎是正确的方法。

我这里是不是快崩溃了?

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:

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.

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.

Am I on crack here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

寒江雪… 2024-08-05 01:18:15

如果我理解正确,这可能会满足您的要求:

template<typename T>
class CVector { ... };

template<typename T>
class CVector<T*> : public CVector< SomeWrapperClass<T> > {
public:
  // for all constructors:
  CVector(...) : CVector< SomeWrapperClass<T> >(...) {
  }
};

它添加了一个额外的继承层来欺骗 CVector成为 CVectorCVector。 SomeWrapperClass; >。 如果您需要添加其他方法以确保 T* 的预期接口与 SomeWrapperClass 提供的接口之间完全兼容,这也可能很有用。

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>.

失眠症患者 2024-08-05 01:18:15

这在 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();
}

This works just fine in 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();
}
面犯桃花 2024-08-05 01:18:15

我不认为你可以使用你描述的语法来专门化一个类......我不知道这可能如何工作。 您可以做的是专门化指针类,并使用原始指针周围的包装类重新实现其内部。 我不确定它是否有帮助,但是这篇文章描述了指针的专用模板。

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 article describes specializing templates for pointers.

内心荒芜 2024-08-05 01:18:15

Boost 类型特征库 可以帮助您实现这一目标。 查看 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(); 
}

The Boost type traits library can help you achieve this. Check out the is_pointer type trait.

#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(); 
}
も星光 2024-08-05 01:18:15

我不认为模板那么灵活。

一种非常强力的方法是专门针对所有指针类型......这解决了使用模板的问题。

您是否可以有一个仅用于指针向量的不同 CVector 类?

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?

酒儿 2024-08-05 01:18:15

我同意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");
}

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.

#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");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文