【问题标题】:How can I initialize members of a class based on a parameter in C++?如何根据 C++ 中的参数初始化类的成员?
【发布时间】:2020-04-24 11:56:06
【问题描述】:

我想实现一个使用 N 维向量的类(从数学的角度来看)。我正在使用 opencv 库中的 Vec 对象,它们的签名如下所示:Vec<typename _Tp, int cn> 其中cn 是该向量内的元素数。我必须为cn 参数提供一个常量。

我希望我的班级看起来像这样:

class MyClass
{
private:
    Vec<float, dim> m_center;
    vector<Vec<float, dim>> m_points;
// ...
}

我希望能够动态初始化dim,即创建一个MyClass 对象,将其dim 设置为我想要的任何数字。如何在 C++ 中正确解决这个问题?

【问题讨论】:

  • template &lt;std::size_t dim&gt; class MyClass ?
  • 你想使用构造函数并传递参数吗?
  • 如果dim不知道编译类型但必须是Vec,那么你必须找到Vec的替代品(如std::vector)。
  • 或者等待JIT Compilation Proposal
  • 如果你有小的可能值,你可能(运行时)调度到所有可能的值。 (if (i == 1) f&lt;1&gt;(); else if (i == 2) f&lt;2&gt;();...)

标签: c++ class generics initialization


【解决方案1】:
template <typename T, int N=9>
class Vec
{
public:
    Vec()
    {
        //auto deleter = [](T* t) { delete[] t; };
        //unique_ptr <T, decltype(deleter)> test(new T[N], deleter); //customized deleter omitted
        t = new T[N];
    }
    Vec(const Vec &v)
    {
        sz = v.sz;
        t = new T[sz];
    }
    string getType()
    {
        return typeid(T).name();
    }
    int getSize()
    {
        return sz;
    }
    ~Vec()
    {
        delete [] t;
    }

private:
    T *t;
    int sz = N;
};

template<int dim = 1>
class MyClass
{
public:
    MyClass()
    {
        m_points.resize(2);
    }
    Vec<float, dim> getCenter()
    {
        return m_center;
    }

    vector<Vec<float, dim>> getPoints()
    {
        return m_points;
    }

private:
    Vec<float, dim> m_center;
    vector<Vec<float, dim>> m_points;
};

测试代码:

int main()
{
    MyClass<10> my;

    cout << "center size = " << my.getCenter().getSize() << endl;
    cout << "center type =" << my.getCenter().getType().c_str() << endl;

    cout << "points size" << my.getPoints().size() << endl;

    cout << "first point size = " << my.getPoints()[0].getSize() << endl;
    cout << "first point type =" << my.getPoints()[0].getType().c_str() << endl;

    std::cout << "Hello World!\n"; 
}

输出:

center size = 10
center type =float
points size2
first point size = 10
first point type =float
Hello World!

【讨论】:

    【解决方案2】:

    编译时值不能是运行时值。

    如果值的范围足够小,您可能会生成所有可能的值并在之后调度。

    看来你只需要处理 1、2 和 3,所以类似于:

    template <std::size_t dim>
    class MyClass
    {
    public:
        void DoFullJob();
    private:
        Vec<float, dim> m_center;
        vector<Vec<float, dim>> m_points;
    // ...
    };
    
    
    int main()
    {
        int i = 0;
        std::cin >> i;
    
        switch (i) {
            case 1: { MyClass<1>{}.DoFullJob(); break; }
            case 2: { MyClass<2>{}.DoFullJob(); break; }
            case 3: { MyClass<3>{}.DoFullJob(); break; }
            default: // Error message, or nothing...
        }
    }
    

    对于更大的范围,switch case 可能被std::index_sequence 生成的函子数组替换。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多