在赋值中转换指针类型

时间:2016-09-29 14:37:10

标签: c++ templates

我有一个课程:

import java.time.{ZonedDateTime, ZonedOffset}

// val yourTimeZoneOffset = ZoneOffset.ofHoursMinutesSeconds(hour, minute, second)

// for example IST or Indian Standard Time has an offset of "+05:30:00" hrs

val istOffset = ZoneOffset.ofHoursMinutesSeconds(5, 30, 0)
// istOffset: java.time.ZoneOffset = +05:30

// time representation in IST
val zonedDateTimeIst = ZonedDateTime.now(istOffset)
// zonedDateTimeIst: java.time.ZonedDateTime = 2016-09-29T20:14:48.048+05:30

val year = zonedDateTimeIst.getYear
// year: Int = 2016

val month = zonedDateTimeIst.getMonth
// month: java.time.Month = SEPTEMBER

val dayOfMonth = zonedDateTimeIst.getDayOfMonth
// dayOfMonth: Int = 29

val df1 = DateTimeFormatter.ofPattern("yyyy - MM - dd")
val df2 = DateTimeFormatter.ofPattern("yyyy/MM/dd")
// df1: java.time.format.DateTimeFormatter = Value(YearOfEra,4,19,EXCEEDS_PAD)' ''-'' 'Value(MonthOfYear,2)' ''-'' 'Value(DayOfMonth,2)
// df2: java.time.format.DateTimeFormatter = Value(YearOfEra,4,19,EXCEEDS_PAD)'/'Value(MonthOfYear,2)'/'Value(DayOfMonth,2)


val dateString1 = zonedDateTimeIst.format(df1)
// dateString1: String = 2016 - 09 - 29
val dateString2 = zonedDateTimeIst.format(df2)
// dateString2: String = 2016/09/29

和我正在做的其中一个功能:

private:
    uint32_t *data;

这很好用。现在我想让它更灵活,所以我想让foo()成为一个模板:

void foo() {
    data = new uint32_t[size];
}

我尝试使用它:

template<typename T>
T foo() {
    data = new T[size];
}

但编译失败说:

class.foo<uint64_t>();

有可能做那样的事吗?我试着宣布

error: cannot convert 'long long unsigned int*' to 'unsigned int*' in assignment

并编译,但后来我不能

void *data;

这就是我需要传递类型的原因。

修改

感谢您的回复,在查看您的答案后,我想添加一些内容。

  • 我正在使用原始指针而不是容器,因为它在外部硬件也使用的内存上运行(我没有在PC上运行它)。
  • 对于此类,使用此内存是可选的,因此如果不需要,我不想分配它。
  • 我在一些我根本不需要*数据的地方使用这个类,所以我宁愿避免让整个类成为模板。

另一个想法: 默认模板类型可能是一个很好的折衷方案,有没有办法创建一个我以后不必使用的类:

sizeof(data[1]);

但仍然:

Class<> my;

如果需要:

Class my;

3 个答案:

答案 0 :(得分:2)

不是将您的函数转换为模板,而是将您的类转换为模板:

template <class T>
class myclass {
private:
    T *data;
public:
    myclass(size_t size) : data(new T[size]) {
    }
    ... // Add copy constructor, assignment operator, and a destructor
        // to properly manage the pointer. See "rule of three" for more info.
};

这样,数组元素的类型成为类的类型的一部分,让您的成员函数与data一起使用,而无需任何其他类型的转换。

请注意,在类中使用原始数组指针在内存管理方面存在重大责任。你最好使用std::vector<T>

答案 1 :(得分:1)

您可以考虑将整个班级设为模板,如下所示:

template <typename T>
class Foo
{
private:
    T *data;
public:
    Foo(size_t size_):
        data{new T[size]}
    {
    }
    ~Foo()
    {
        delete[] data;
    }
};

这里的实施只是部分的。请参阅rule of 3, 5, 0

或使用托管指针:

template <typename T>
class Foo
{
private:
    std::unique_ptr<T[]> data;
    size_t size;
public:
    Foo(size_t size_):
        data{std::make_unique<T[]>(size_)},
        size(size_)
    {
    }
    ~Foo()
    {
        // no need to call delete, unique_ptr will do it
    }
};

但是一旦你来到这里,根据你的使用情况,替代方案可能更可取,例如std::vector

std::vector<uint64_t> v(size);
// ...
std::cout << v.size() << std::endl;

修改

根据您提供的其他信息,以下设计可能更适合您的需求:

class Base
{
public:
    virtual void* get_data() {
        return nullptr;
    }
    virtual size_t get_size() {
        return 0;
    }
};

template<typename T>
class Foo : public Base
{
private:
    T* data;
    size_t size;
public:
    Foo(size_t size_):
        data{new T[size_]},
        size(size_) {}
    ~Foo() {
        delete[] this->data; // same remark as above about rule of 5
    }
    virtual void* get_data() overriden {
        return this->data;
    }
    virtual size_t get_size() overriden {
        return this->size;
    }
};

具有以下用途:

std::unique_ptr<Base> my_without_data =
    std::make_unique<Base>();

std::unique_ptr<Base> my_with_data =
    std::make_unique<Foo<type>>(size);

请注意,在第二次通话中,std::make_unique会返回一个unique_ptr<Foo<type>>,其中有一个适当的删除者,正在调用Foo<type>的析构函数。即使my_with_data的析构函数未声明为虚拟,也会在分配给Foo<type>时调用删除者并调用Base的析构函数。

我在这里选择了Base中带有虚拟方法的设计来访问data。根据您的实际使用情况,可以使用其他方式。

答案 2 :(得分:1)

将您的整个班级转换为模板类

template<typename T>
class Container {
public:
    Container() :
        data(NULL)
    {}
    ~Container() {
        if (data) {
            delete [] data;
        }
    }
    T* foo(int size) {
        if (data) {
            delete [] data;
        }
        data = new T[size];
        return data;
    }
private:
    T *data;
};