如何在没有 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}
        };
};

https://godbolt.org/z/sjbE4B

为简单起见,我保留了手动指定的尺寸。可能有一种方法不仅可以推断大小,还可以推断 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;
}