如何在没有 std::initializer_list 的情况下列出初始化模板 class,使其具有固定大小
how to list initialise a templated class without std::initializer_list so it has a fixed size
不使用 stdlib(由于 arduino 平台)我正在尝试创建一个像 class 这样的映射,我可以使用给定字符串的 运行 函数。它的大小需要在创建时固定。所以我一直在尝试弄清楚如何使用模板或可变参数模板来创建它,但我还不够精通,无法让它发挥作用。
理想情况下,它的创建方式与此类似
class parent_class {
StringMap mymap{
{ "command1", parent_class::member_function },
{ "command2", parent_class::member_function },
...
};
...
}
但我一直在努力寻找模板和可变参数的正确组合,我最终确实得到了一些与 std::initializer_list 一起工作的东西,但是我在 arduino 平台上不可用,所以它不是初学者。
我真的不在乎它在幕后是如何工作的,我已经通过文档和示例来找到实现这一目标的方法,我觉得它应该能够完成。
然后我将使用它在地图上进行二进制搜索,如果没有完全匹配,则将显示最近的邻居到下一个最佳的建议。但我被困在底层机制上。下面是我在卡住和重写然后再次卡住之前得到的最接近的结果。
#include <string>
template< typename T >
struct Pair {
std::string path;
T object;
};
template< class T >
struct StringMap {
StringMap( T args[] ){
}
};
class Parent {
void testfunc(int data){}
void testfunc2(int data){}
StringMap<void (Parent::*)(int)> map{
Pair<void (Parent::*)(int)>{"command1", &Parent::testfunc},
Pair<void (Parent::*)(int)>{"command2", &Parent::testfunc2}
};
};
int main(){
Parent test;
//Then i could run something like test.run("command1", 1);
return 0;
}```
Compiler commandline for the arduino studio starts like this:
avr-gcc/5.4.0-atmel3.6.1-arduino2/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega2560
我想你试试这样的方法:
template<class T, bool(*cmp)(int,int)>
class strMap{
};
一种方法是仅依赖普通数组成员的聚合初始化:
template< class T, int N>
struct StringMap {
// Do not add a constructor!
Pair<T> values[N];
};
class Parent {
void testfunc(int data){}
void testfunc2(int data){}
StringMap<void (Parent::*)(int), 2> map{
Pair<void (Parent::*)(int)>{"command1", &Parent::testfunc},
Pair<void (Parent::*)(int)>{"command2", &Parent::testfunc2}
};
};
为简单起见,我保留了手动指定的尺寸。可能有一种方法不仅可以推断大小,还可以推断 T
,但我认为这样代码不会变得更清晰。
另请注意,如果您指定的 N
太大,则剩余的数组条目将被零初始化,您必须正确设置该条目。 (但是如果你使用了太多的初始化器,你会得到一个编译时错误)。
所以我回去查看了更多有关统一初始化的文档,并以此作为起点,但我希望尽可能简化它。在 godbolt.org 和 arduino studio 中编译。
#include <string>
template<typename T>
struct Pair {
std::string first;
T second;
};
template<class T,int size>
struct Map {
template<class... Ts> //somehow enableif size and parameter pack match
Map(Ts ...input){
for( int i = 0; i < sizeof...(input); ++i){
}
}
//Rudimentary linear search
T find(std::string name){
for( auto i : list){
if(! i.first.compare(name) ) return i.second;
}
}
Pair<T> list[size];
};
struct Parent{
void func1( int num ){}
void func2( int num ){}
void func3( int num ){}
Map<void (Parent::*)(int),3> map{
Pair<void (Parent::*)(int)>{"func1",&Parent::func1},
Pair<void (Parent::*)(int)>{"func2",&Parent::func2},
Pair<void (Parent::*)(int)>{"func3",&Parent::func3}
};
void call(std::string name){
auto func = map.find(name);
(this->*func)( 1 );
}
};
int main(){
Parent parent;
parent.call("func1");
return 0;
}
不使用 stdlib(由于 arduino 平台)我正在尝试创建一个像 class 这样的映射,我可以使用给定字符串的 运行 函数。它的大小需要在创建时固定。所以我一直在尝试弄清楚如何使用模板或可变参数模板来创建它,但我还不够精通,无法让它发挥作用。
理想情况下,它的创建方式与此类似
class parent_class {
StringMap mymap{
{ "command1", parent_class::member_function },
{ "command2", parent_class::member_function },
...
};
...
}
但我一直在努力寻找模板和可变参数的正确组合,我最终确实得到了一些与 std::initializer_list 一起工作的东西,但是我在 arduino 平台上不可用,所以它不是初学者。
我真的不在乎它在幕后是如何工作的,我已经通过文档和示例来找到实现这一目标的方法,我觉得它应该能够完成。
然后我将使用它在地图上进行二进制搜索,如果没有完全匹配,则将显示最近的邻居到下一个最佳的建议。但我被困在底层机制上。下面是我在卡住和重写然后再次卡住之前得到的最接近的结果。
#include <string>
template< typename T >
struct Pair {
std::string path;
T object;
};
template< class T >
struct StringMap {
StringMap( T args[] ){
}
};
class Parent {
void testfunc(int data){}
void testfunc2(int data){}
StringMap<void (Parent::*)(int)> map{
Pair<void (Parent::*)(int)>{"command1", &Parent::testfunc},
Pair<void (Parent::*)(int)>{"command2", &Parent::testfunc2}
};
};
int main(){
Parent test;
//Then i could run something like test.run("command1", 1);
return 0;
}```
Compiler commandline for the arduino studio starts like this:
avr-gcc/5.4.0-atmel3.6.1-arduino2/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega2560
我想你试试这样的方法:
template<class T, bool(*cmp)(int,int)>
class strMap{
};
一种方法是仅依赖普通数组成员的聚合初始化:
template< class T, int N>
struct StringMap {
// Do not add a constructor!
Pair<T> values[N];
};
class Parent {
void testfunc(int data){}
void testfunc2(int data){}
StringMap<void (Parent::*)(int), 2> map{
Pair<void (Parent::*)(int)>{"command1", &Parent::testfunc},
Pair<void (Parent::*)(int)>{"command2", &Parent::testfunc2}
};
};
为简单起见,我保留了手动指定的尺寸。可能有一种方法不仅可以推断大小,还可以推断 T
,但我认为这样代码不会变得更清晰。
另请注意,如果您指定的 N
太大,则剩余的数组条目将被零初始化,您必须正确设置该条目。 (但是如果你使用了太多的初始化器,你会得到一个编译时错误)。
所以我回去查看了更多有关统一初始化的文档,并以此作为起点,但我希望尽可能简化它。在 godbolt.org 和 arduino studio 中编译。
#include <string>
template<typename T>
struct Pair {
std::string first;
T second;
};
template<class T,int size>
struct Map {
template<class... Ts> //somehow enableif size and parameter pack match
Map(Ts ...input){
for( int i = 0; i < sizeof...(input); ++i){
}
}
//Rudimentary linear search
T find(std::string name){
for( auto i : list){
if(! i.first.compare(name) ) return i.second;
}
}
Pair<T> list[size];
};
struct Parent{
void func1( int num ){}
void func2( int num ){}
void func3( int num ){}
Map<void (Parent::*)(int),3> map{
Pair<void (Parent::*)(int)>{"func1",&Parent::func1},
Pair<void (Parent::*)(int)>{"func2",&Parent::func2},
Pair<void (Parent::*)(int)>{"func3",&Parent::func3}
};
void call(std::string name){
auto func = map.find(name);
(this->*func)( 1 );
}
};
int main(){
Parent parent;
parent.call("func1");
return 0;
}