variadic templates & pass by const reference & member operator [] in const map & gcc sucks

时间:2022-07-28 07:03:04
/// bugs code with comments
#include <iostream>
#include <memory>
#include <unordered_map>

using namespace std;

class A
{
public:
    A(const std::unordered_map<int, int > &ref) : ref_m(ref) {}

    void test1(int index) {
        // std::cout << ref_m[index] << std::endl; // bugs version in c++ specification, mainly sucks in gcc compile error prompts.
        std::cout << ref_m.at(index) << std::endl; // or ref_m.find() etc.
    }

    // this function will crash, as a result of ref_m get a wrong memory address by value passing instead of reference passing in gcc
    void test2() {
        for(auto& e: ref_m)
            std::cout << e.first << ' '<< e.second << std::endl;
    }

    void print_ref_size() {
        std::cout << "ref_m size: " <<  ref_m.size() << std::endl;
    }

private:
    const std::unordered_map<int, int >& ref_m;
};

template <typename ManipulatorType, typename ... Args>
std::shared_ptr<ManipulatorType> CreateTester(std::string name, Args ... args)
{
    return std::make_shared<ManipulatorType>(args ...);
}

class B{
public:
    B(){}

    std::shared_ptr<A> CreateATesterWrapper() {
        // return CreateTester<A>("uselessparams", ref); // bugs version in gcc
        return CreateTester<A>("uselessparams", std::ref(ref)); // or replace "Args ... args" with "Args& ... args"  in gcc
    }

    void print_ref_size() {
        std::cout << "ref size: " <<  ref.size() << std::endl;
    }

    std::unordered_map<int, int > ref = {{1,2}};
};

int main(int argc, char* argv[])
{
    B b;
    auto a = b.CreateATesterWrapper();
    b.print_ref_size();
    a->print_ref_size();
    a->test1(1);
    a->test2();
    return 0;
}