【问题标题】:How to pass template arguments via constructor?如何通过构造函数传递模板参数?
【发布时间】:2020-05-30 14:27:50
【问题描述】:

我正在寻找一种方法来通过我自己的类的构造函数(它基本上应该包装 FastLED 库)传递基于模板的类(具体来说是FastLED library on Arduino 的主类)的模板参数)。我想在主函数中指定初始化 FastLED 所需的模板参数,以便编译前的所有预配置(即下面第三个代码块中的 #defines)通过主文件中的常量工作。我怎样才能做到这一点?

目前,我的班级是这样的:

LEDState.h:

#pragma once
#include "FastLED.h"
FASTLED_USING_NAMESPACE

class LEDState {
  private:
    CRGB* _leds;
    CRGB* _pixels;
    const uint16_t _pixel_count;
    const uint16_t _led_count;
    const uint8_t _mapmode;

  public:
    LEDState(const uint16_t pixel_count, const uint8_t mapmode);
    void show();
};

LEDState.cpp:

#include "LEDState.h"

LEDState::LEDState(const uint16_t pixel_count, const uint8_t mapmode)
: _pixel_count(pixel_count), _mapmode(mapmode), _led_count(_pixel_count * (_mapmode & 0x0f))
{
  _leds = (CRGB*)malloc(_led_count * sizeof(CRGB));
  _pixels = (CRGB*)malloc(_pixel_count * sizeof(CRGB));
  FastLED.addLeds<CHIPSET, DATA_PIN, CLOCK_PIN, COLOR_ORDER>(_leds, _led_count);
}

void LEDState::show() {
  for( int p = 0; p < _pixel_count; p++ ) {
    _leds[p] = _pixels[p];
  }
  FastLED.show();
}

我的问题是我没有找到通过LEDState的构造函数传递模板参数&lt;CHIPSET, DATA_PIN, CLOCK_PIN, COLOR_ORDER&gt;的方法。

有没有办法从我的主文件初始化我的包装类包装的 FastLED 库?我想象我的main.ino 文件是这样的:

#include "LEDState.h"

#define CHIPSET APA102
#define DATA_PIN 23
#define CLOCK_PIN 18
#define COLOR_ORDER GRB 

LEDState state = LEDState<CHIPSET, DATA_PIN, CLOCK_PIN, COLOR_ORDER>(led_count, map_mode);

void setup() {
}

void loop() {
  LEDState.show();
}

APA102GRB 是 FastLED 库中的常量。)

这样的事情可能吗?

(我不确定我知道寻找解决方案的正确词汇,更不用说在这个问题中使用正确的术语了。我发现的所有内容要么不是我的问题的解决方案,要么我不明白这是一个解决方案。我来自“普通的 Arduino C”;我对 C++ 模板的了解大致在:我可以通过修补现有模板代码来工作,但我不知道如何创建模板。)

编辑:有了 cmets 和第一个答案,我想我的课程也需要模板化。我尝试从 FastLED 库中复制模板参数列表(请参阅上面的链接),从而得到此类定义:

template<ESPIChipsets CHIPSET, uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder COLOR_ORDER>
class LEDState {
  ...
}

ESPIChipsetsEOrder 由 FastLED 定义)

现在编译器抱怨

LEDState.cpp:3:1: error: invalid use of template-name 'LEDState' without an argument list
 LEDState::LEDState(const uint16_t pixel_count, const uint8_t mapmode)
 ^

我还需要什么来编译它?

【问题讨论】:

  • 我不关注.. 如果您需要 LEDState 作为模板,是什么阻止您将其设为模板?
  • @AlgirdasPreidžius 因为我不知道它本身需要是一个基于模板的类。如果确实如此,我的问题是“我需要知道什么才能将我的课程变成模板?”
  • @orithena I don't know that it would need to be a template-based class itself 我们也不知道,因为不清楚这对您是否重要,so that all pre-configuration before compiling works 也不清楚。我们不知道你从哪里得到CHIPSETDATA_PINCLOCK_PINCOLOR_ORDER
  • 显示Minimal, Reproducible Example会有所帮助
  • 我怀疑您只需要模板化您的 LEDState 构造函数。这样您就可以简单地将模板参数传递给FastLED.addLeds 调用。

标签: c++ class templates constructor


【解决方案1】:

我建议您查看 FastLED 实现,它完全按照您想要使用包装类的方式编写。我缺少一些库,所以我无法判断所有内容是否都能编译,但解决方案必须接近此

template <ESPIChipsets chipset, uint8_t data_pin, uint8_t clock_pin, EOrder rgb_order = RGB>
class LEDState {
private:
  std::unique_ptr<CRGB[]> _leds;
  std::unique_ptr<CRGB[]> _pixels;
  const uint16_t _pixel_count = 0;
  const uint16_t _led_count = 0;
  const uint8_t _mapmode = 0;

public:
  LEDState(const uint16_t pixel_count, const uint8_t mapmode)
    : _pixel_count(pixel_count), _mapmode(mapmode), _led_count(_pixel_count* (_mapmode & 0x0f))
  {
    if (_pixel_count > 0)
    {
      _leds = std::make_unique(new CRGB[_led_count]);
      _pixels = std::make_unique(new CRGB[_pixel_count]);
      FastLED.addLeds<chipset, data_pin, clock_pin, rgb_order>(_leds, _led_count, RGB_ORDER);
    }
  }
  void show() {
  }
};

#define CHIPSET APA102
#define DATA_PIN 23
#define CLOCK_PIN 18
#define COLOR_ORDER GRB 

int main()
{
  const uint16_t pixel_count = 3;
  const uint8_t map_mode = 0;
  LEDState<CHIPSET, DATA_PIN, CLOCK_PIN, COLOR_ORDER> state(pixel_count, map_mode);
}

【讨论】:

  • 谢谢,我尝试遵循该方法(我也确实将构造函数移至 .h 文件,因为我今天在某处读到,这在模板类中是必需的),但仍然缺少一些东西:编译器在 LEDState.cpp 中的 LEDState::show() 上抱怨“'template class LEDState' used without template parameters”。
  • 另外,我对模板的了解还不够,无法从 FastLED 库中实际提取信息。那里的模板太多了,我无法找到我需要的示例。
  • 当你使用模板类时,你必须将每个方法移动到头部。我更新了答案以反映这一点。
  • 谢谢,这似乎是缺少的信息(我不知道我从哪里得到的信息,我只需要移动那些实际使用模板参数的方法......)跨度>
【解决方案2】:

没有。你想做的事是不可能的。

您的问题与this 有关,同样的答案也适用。

您想要做的将通过类模板来实现。例如:

template<std::size_t N> class foo { /* interface*/ };

然后您可以按照您的需要非常相似地实例化它:

foo<10> bar;
/* Use bar */

【讨论】:

    【解决方案3】:

    你似乎真的想要一个类模板。以下是如何在 C++ 中创建一个

    #include <iostream>
    
    template < class T >
    class my_class {
    
        public:
            typedef T type;
    
            my_class() {
                std::cout << sizeof( type ) << '\n';
            }
    
    };
    
    int main()
    {
        auto A = my_class< double >();
        auto B = my_class< float >();
        auto C = my_class< char >();
    
        return 0;
    }
    

    【讨论】:

    • 谢谢,我确实已经找到了这个简单的例子,但我不知道如何将它映射到我的问题。我将模板参数列表从FastLED.addLeds 复制到我的班级(导致template&lt;ESPIChipsets CHIPSET, uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder COLOR_ORDER&gt; class LEDState),然后给了我编译器错误“'template class LEDState' used没有模板参数”使用上面的主要代码。
    猜你喜欢
    • 1970-01-01
    • 2021-07-16
    • 2018-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多