C++:"("令牌"之前有预期的非限定 id 指向类中成员函数的指针

C++: 'expected unqualified-id before '(' token' Pointer to Member Functions in a Class

本文关键字:id 指针 函数 成员 令牌 C++      更新时间:2023-10-16

所以我尝试在下面的代码中调用成员函数指针,使用typedef void (CommandHandler::*pfunc)(std::vector<String>&)的成员函数指针映射 但是,我在使语法工作时遇到问题,因为我收到以下错误: "("标记之前应为非限定 ID

请注意,这是Arduino,ArduinoSTL支持大多数STL调用。

此行失败,注释掉此行会导致代码确实可以编译。

((this).(*(this.cmd_func)))(parses);

我尝试了我在网上看到的不同语法,例如 https://isocpp.org/wiki/faq/pointers-to-members。 即使在该语法中,它也会导致错误。(例如,使用下面的宏仍然导致错误(

#define CALL_MEMBER_FN(object,ptrToMember)  ((object).*(ptrToMember))

我有一种感觉,这与我的 typedef 类型有关,编译器在查看代码时(立即(吐出一个没有意义的错误。谁能帮我理解为什么这段代码失败?谢谢!

完整文件如下

#include <ArduinoSTL.h>
#include<map>
#include <vector>
#include <Adafruit_NeoPixel.h>
#include <iostream>
#include <string>
#include <EEPROM.h>
#define LED_PIN    4
#define LED_COUNT 12
#define MY_ROLE 0
//#define CALL_MEMBER_FN(object,ptrToMember)  ((object).*(ptrToMember)) //This call doesn't work in Arduino
#define X_ADDR 0
#define Y_ADDR 1
#define MY_ROLE 2
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
class CommandHandler{
typedef void (CommandHandler::*pfunc)(std::vector<String>&);
CommandHandler::CommandHandler(){
x = EEPROM.read(X_ADDR);
y = EEPROM.read(Y_ADDR);
role_id = MY_ROLE;
init_commands_with_args();
}
CommandHandler::CommandHandler(int x, int y, int role_id){
this->x = x;
this->y = y;
this->role_id = role_id;
init_commands_with_args();
}
public:
int x, y, role_id;
std::map<String, pfunc> commandsTable; 
void set_red(){show_led_int(255,0,0);}
void set_green(){show_led_int(0,255,0);}
void set_blue(){show_led_int(0,0,255);}
void set_purple(){show_led_int(255, 0, 255);}
void set_yellow(){show_led_int(255, 255, 0);}
void set_cyan(){show_led_int(0,255,255);}
void set_white(){show_led_int(255,255,255);}
void set_none(){show_led_int(0,0,0);}
void init_commands_with_args(){
commandsTable["a"] = &show_led;
//commandsTable["b"] = &blink_color;
//commandsTable["c"] = &theaterChase;
//commandsTable["d"] = &rainbow;
//commandsTable["e"] = &theaterChaseRainbow;
return;
}
void handle_command(std::string input, std::string delimiter = "/"){
if (input.size() == 1){
switch(input[0]){
case 'R':
CommandHandler::set_red();
case 'B':
CommandHandler::set_blue();
case 'G':
CommandHandler::set_green();
case 'W':
CommandHandler::set_white();
case 'P':
CommandHandler::set_purple();
case 'C':
CommandHandler::set_cyan();
case 'Y':
CommandHandler::set_yellow();
case 'N':
CommandHandler::set_none();
}
}
else{
std::vector<String> parses; // 10 maximum args
size_t pos = 0; size_t i = 0;
String token;
//std::string tokens = s.substr(0, s.find(delimiter));
while ((pos = input.find(delimiter)) != std::string::npos) {
token = String(input.substr(0, pos).c_str());
//std::cout << token << std::endl;
parses.push_back(token);
input.erase(0, pos + delimiter.length());
i++;
}
//Parses is now an array of strings.
pfunc cmd_func = commandsTable[parses[0]];
parses.erase(parses.begin());
((this).(*(this.cmd_func)))(parses); //This line fails no matter what I try to do. //Expected unqualified-id before '(' token
//I want to call the function of this instance that is in commandsTable, with arguments defined in the vector parses.
//The first element of the vector which is later erased is the function in commandsTable that is mapped
//Other elements are arguments in the string.
}
}

void blink(){
delay(0.5*role_id);
this->show_led_int(255, 255, 255);
delay(0.5);
this->show_led_int(0, 0, 0);
}
//void blink_color(int r, int b, int g){
void blink_color(std::vector<String> & input){
int r = String(input[0].c_str()).toInt();
int b = String(input[1].c_str()).toInt();
int g = String(input[2].c_str()).toInt();  
uint32_t mycolor = strip.Color(r, b, g);
delay(0.5*role_id);
this->show_led_int(r, b, g);
delay(0.5);
this->show_led_int(0, 0, 0);
}
//void show_led(int r, int b, int g){
void show_led(std::vector<String> & input){
int r = String(input[0].c_str()).toInt();
int b = String(input[1].c_str()).toInt();
int g = String(input[2].c_str()).toInt();  
uint32_t mycolor = strip.Color(r, b, g);
strip.setPixelColor(0, mycolor);
strip.setPixelColor(1, mycolor);
strip.setPixelColor(2, mycolor);
strip.setPixelColor(3, mycolor);
strip.setPixelColor(4, mycolor);
strip.setPixelColor(5, mycolor);
strip.setPixelColor(6, mycolor);
strip.setPixelColor(7, mycolor);
strip.setPixelColor(8, mycolor);
strip.setPixelColor(9, mycolor);
strip.setPixelColor(10, mycolor);
strip.setPixelColor(11, mycolor);
strip.show();
}
void show_led_int(int r, int b, int g){
uint32_t mycolor = strip.Color(r, b, g);
strip.setPixelColor(0, mycolor);
strip.setPixelColor(1, mycolor);
strip.setPixelColor(2, mycolor);
strip.setPixelColor(3, mycolor);
strip.setPixelColor(4, mycolor);
strip.setPixelColor(5, mycolor);
strip.setPixelColor(6, mycolor);
strip.setPixelColor(7, mycolor);
strip.setPixelColor(8, mycolor);
strip.setPixelColor(9, mycolor);
strip.setPixelColor(10, mycolor);
strip.setPixelColor(11, mycolor);
strip.show();
}
//void colorWipe(uint32_t color, int wait) {
void colorWipe(std::vector<String> & input){
uint32_t color = String(input[0].c_str()).toInt();;
int wait = String(input[0].c_str()).toInt();;
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
strip.show();                          //  Update strip to match
delay(wait);                           //  Pause for a moment
}
}
//void theaterChase(uint32_t color, int wait) {
void theaterChase(std::vector<String> & input){
uint32_t color = String(input[0].c_str()).toInt();
int wait = String(input[1].c_str()).toInt();
for(int a=0; a<10; a++) {  // Repeat 10 times...
for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
strip.clear();         //   Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in steps of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait);  // Pause for a moment
}
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
//void rainbow(int wait) {
void rainbow(std::vector<String> & input){
int wait = String(input[0].c_str()).toInt();
for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
// Offset pixel hue by an amount to make one full revolution of the
// color wheel (range of 65536) along the length of the strip
// (strip.numPixels() steps):
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
// strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
// optionally add saturation and value (brightness) (each 0 to 255).
// Here we're using just the single-argument hue variant. The result
// is passed through strip.gamma32() to provide 'truer' colors
// before assigning to each pixel:
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
strip.show(); // Update strip with new contents
delay(wait);  // Pause for a moment
}
}
// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
//void theaterChaseRainbow(int wait) {
static void theaterChaseRainbow(std::vector<String> & input){
int wait = String(input[0].c_str()).toInt();
int firstPixelHue = 0;     // First pixel starts at red (hue 0)
for(int a=0; a<30; a++) {  // Repeat 30 times...
for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
strip.clear();         //   Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in increments of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
// hue of pixel 'c' is offset by an amount to make one full
// revolution of the color wheel (range 65536) along the length
// of the strip (strip.numPixels() steps):
int      hue   = firstPixelHue + c * 65536L / strip.numPixels();
uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show();                // Update strip with new contents
delay(wait);                 // Pause for a moment
firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
}
}
}
void updateRole(std::vector<String> & input){
this->role_id = input[0].toInt();
}
void updateLoc(std::vector<String> & input){
this->x = input[0].toInt();
this->y = input[1].toInt();
EEPROM.write(X_ADDR, this->x);
EEPROM.write(Y_ADDR, this->y);
}
};
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}

调用指向成员的指针看起来会有点复杂。 由于this是一个指针,并且CALL_MEMBER_FN需要引用,因此您可以将宏用作

CALL_MEMBER_FN(*this, this->cmd_func)(parses);

或者,没有宏,

(this->*(this->cmd_func))(parses);