C++ 如何设计getData()的返回类型? #包括 #包括 typedef无符号字符uint8; 枚举类类型标志{ kFloat32=0, kFloat64=1, kUint8=2 }; 等级:Ndaray; 模板 类TBlob{ 朋友班; 公众: TBlob():dptr_(nullptr){}; TBlob(size_t size):dptr(new t[size]){}; ~TBlob(){if(dptr_)delete[]dptr_;} 私人: T*dptr; }; 使用datahandle=std::variant; 班轮{ 公众: NDArray():dtype_(typeFlag::kFloat32){ NDArray(size_t size,typeFlag dtype):dtype_(dtype){alloc(size);} ~NDArray(){if(&data)}删除&data;} 空隙分配(尺寸){ 开关(数据类型){ 案例类型标志::kFloat32: 数据=新的TBlob(大小); 打破 案例类型标志::kFloat64: 数据=新的TBlob(大小); 打破 案例类型标志::kUint8: 数据=新的TBlob(大小); 打破 违约: 数据=新的TBlob(大小); 打破 } } 常量自动获取数据(){ if(dtype \==typeFlag::kFloat32)返回std::get(data \)->dptr; else if(dtype \==typeFlag::kFloat64)返回std::get(data \)->dptr; 否则返回std::get(data)->dptr; } 私人: typeFlag-dtype; 数据处理数据; }; int main(){ NDArray a(5,typeFlag::kUint8); std::cout dptr_u; ^~~~~

C++ 如何设计getData()的返回类型? #包括 #包括 typedef无符号字符uint8; 枚举类类型标志{ kFloat32=0, kFloat64=1, kUint8=2 }; 等级:Ndaray; 模板 类TBlob{ 朋友班; 公众: TBlob():dptr_(nullptr){}; TBlob(size_t size):dptr(new t[size]){}; ~TBlob(){if(dptr_)delete[]dptr_;} 私人: T*dptr; }; 使用datahandle=std::variant; 班轮{ 公众: NDArray():dtype_(typeFlag::kFloat32){ NDArray(size_t size,typeFlag dtype):dtype_(dtype){alloc(size);} ~NDArray(){if(&data)}删除&data;} 空隙分配(尺寸){ 开关(数据类型){ 案例类型标志::kFloat32: 数据=新的TBlob(大小); 打破 案例类型标志::kFloat64: 数据=新的TBlob(大小); 打破 案例类型标志::kUint8: 数据=新的TBlob(大小); 打破 违约: 数据=新的TBlob(大小); 打破 } } 常量自动获取数据(){ if(dtype \==typeFlag::kFloat32)返回std::get(data \)->dptr; else if(dtype \==typeFlag::kFloat64)返回std::get(data \)->dptr; 否则返回std::get(data)->dptr; } 私人: typeFlag-dtype; 数据处理数据; }; int main(){ NDArray a(5,typeFlag::kUint8); std::cout dptr_u; ^~~~~,c++,templates,C++,Templates,似乎getData()函数总是根据dtype\uu的默认值返回一个float*类型,即float 如何根据dtype\uuuu的运行时值返回不同的类型?我需要处理getData()返回的指针,这些操作与此指针的类型无关。例如: NDArray NDArray::运算符*(常量浮点标量)常量{ NDArray ret(*本); 对于(尺寸i=0;i 单个非模板函数(或类成员)的返回类型不能依赖于某个运行时值(dtype),这是错误的核心。编译器尝试推断单个返回类型,但失败了,因为不同的代码路径返回

似乎
getData()
函数总是根据
dtype\uu
的默认值返回一个
float*
类型,即
float

如何根据
dtype\uuuu
的运行时值返回不同的类型?我需要处理
getData()
返回的指针,这些操作与此指针的类型无关。例如:

NDArray NDArray::运算符*(常量浮点标量)常量{
NDArray ret(*本);
对于(尺寸i=0;i
  • 单个非模板函数(或类成员)的返回类型不能依赖于某个运行时值(
    dtype
    ),这是错误的核心。编译器尝试推断单个返回类型,但失败了,因为不同的代码路径返回
    float*
    double*
    uint8.
  • 您的操作并不依赖于指针的类型。在这一行中,
    ret.getData()[i]*=scalar
    您已经需要知道类型,以便正确索引(部分)和正确乘法(部分)
  • 您可以在这里做很多选择。我建议将
    NDArray
    制作成一个模板本身,它可以保存一个数据指针和一个大小,而不带任何类型标志。这将使事情变得更加简单和经得起未来考验(例如,如果您决定还需要存储
    uint16\u t
    ,则不会有任何中断)

    但是,如果您绝对必须使用此3类型布局,并对该类型进行运行时推断,则可以大致执行以下操作。添加一个
    apply
    函数,该函数将接受任何可调用对象,并使用适当的数据类型调用它,例如

    class NDArray {
        ...
        template <typename F>
        void apply(F f) {
            if (dtype_ == typeFlag::kFloat32)
                f(std::get<0>(data_)->dptr_, getSize());
            else if (dtype_ == typeFlag::kFloat64)
                f(std::get<1>(data_)->dptr_, getSize());
            else
                f(std::get<2>(data_)->dptr_, getSize());
        }
        ...
    };
    
    注意,为了简单起见,这个
    apply
    复制了callable,但是它应该接受转发引用并进行适当的转发,如

    template <typename F>
    void apply(F && f) {
       ...
       std::forward<F>(f)(std::get<0>(data_)->dptr_, getSize());
       ...
    }
    
    模板
    无效应用(F&F){
    ...
    std::forward(f)(std::get(data)->dptr,getSize());
    ...
    }
    
  • 单个非模板函数(或类成员)的返回类型不能依赖于某个运行时值(
    dtype
    ),这是错误的核心。编译器尝试推断单个返回类型,但失败了,因为不同的代码路径返回
    float*
    double*
    uint8.
  • 您的操作并不依赖于指针的类型。在这一行中,
    ret.getData()[i]*=scalar
    您已经需要知道类型,以便正确索引(部分)和正确乘法(部分)
  • 您可以在这里做很多选择。我建议将
    NDArray
    制作成一个模板本身,它可以保存一个数据指针和一个大小,而不带任何类型标志。这将使事情变得更加简单和经得起未来考验(例如,如果您决定还需要存储
    uint16\u t
    ,则不会有任何中断)

    但是,如果您绝对必须使用此3类型布局,并对该类型进行运行时推断,则可以大致执行以下操作。添加一个
    apply
    函数,该函数将接受任何可调用对象,并使用适当的数据类型调用它,例如

    class NDArray {
        ...
        template <typename F>
        void apply(F f) {
            if (dtype_ == typeFlag::kFloat32)
                f(std::get<0>(data_)->dptr_, getSize());
            else if (dtype_ == typeFlag::kFloat64)
                f(std::get<1>(data_)->dptr_, getSize());
            else
                f(std::get<2>(data_)->dptr_, getSize());
        }
        ...
    };
    
    注意,为了简单起见,这个
    apply
    复制了callable,但是它应该接受转发引用并进行适当的转发,如

    template <typename F>
    void apply(F && f) {
       ...
       std::forward<F>(f)(std::get<0>(data_)->dptr_, getSize());
       ...
    }
    
    模板
    无效应用(F&F){
    ...
    std::forward(f)(std::get(data)->dptr,getSize());
    ...
    }
    
    我将模板
    数据
    并删除
    数据类型

    template <typename TData>
    class NDArray
    {
        public:
            ...
            const TData getData() { return std::get<0>(data_)->dptr_; }
    
        private:
            TData data_;
    }
    

    我将模板
    数据
    并删除
    数据类型

    template <typename TData>
    class NDArray
    {
        public:
            ...
            const TData getData() { return std::get<0>(data_)->dptr_; }
    
        private:
            TData data_;
    }
    

    无法从单个函数执行此操作,因为返回类型不是函数签名的一部分。例如,
    int foo();
    double foo();
    是同一个函数,因此不能同时存在

    由于您的代码已在内部使用变体,因此您可以将访问函数设计为类似于
    std::variant
    。例如,将访问器作为模板:

    template <typeFlag Type>
    auto const & getData () {
      if constexpr (Type == typeFlag::kFloat32) { return std::get<0>(data_)->dptr_; }
      else if constexpr (Type == typeFlag::kFloat64) { return std::get<1>(data_)->dptr_; }
      else { return std::get<2>(data_)->dptr_; }
    }
    
    模板
    自动常量和获取数据(){
    如果constexpr(Type==typeFlag::kFloat32){返回std::get(data)->dptr}
    如果constexpr(Type==typeFlag::kFloat64){return std::get(data)->dptr}
    else{return std::get(data)->dptr}
    }
    
    当然,这需要调用方知道哪个模板