c++ 如何消除这种重复

uinbv5nw  于 2023-03-20  发布在  其他
关注(0)|答案(2)|浏览(156)

我有这样的代码:

struct A1{
    void do_something1(int t, ... ){
        switch(t){
            default:
            case  8: return process_<uint8_t >(a, b, c);
            case 16: return process_<uint16_t>(a, b, c);
            case 32: return process_<uint32_t>(a, b, c);
            case 64: return process_<uint64_t>(a, b, c);
        }
    }
       
    template<typename T>
    void process_(...){
    }
};
    
struct A2{
    void do_something2(int t, ... ){
        switch(t){
            default:
            case  8: return process_<uint8_t >(d, e, f);
            case 16: return process_<uint16_t>(d, e, f);
            case 32: return process_<uint32_t>(d, e, f);
            case 64: return process_<uint64_t>(d, e, f);
        }
    }
       
    template<typename T>
    void process_(...){
    }
};

具有类似开关的几个类将相同的参数“转发”到另一个具有模板参数而不是方法参数t的方法。
目前,如果我需要更改process_的参数,我需要将它们写入4次。
是否有简单的方法可以删除此重复项?
例如,代替4个几乎相同的行,仅具有1-2行代码。

switch(t){
    default:
    case  8: return process_<uint8_t >(d, e, f);
    case 16: return process_<uint16_t>(d, e, f);
    case 32: return process_<uint32_t>(d, e, f);
    case 64: return process_<uint64_t>(d, e, f);
}

我可以考虑方法指针,但我不确定如何做。

8e2ybdfx

8e2ybdfx1#

你可以创建一个helper函数,将运行时值t“提升”为四种类型之一,并将其传递给一个lambda:

// C++20 version
template<typename Lambda>
decltype(auto) select_type(int t, const Lambda& l) {
    switch (t) {
        default:
        case 8 : return l.template operator()<std::uint8_t >();
        case 16: return l.template operator()<std::uint16_t>();
        case 32: return l.template operator()<std::uint32_t>();
        case 64: return l.template operator()<std::uint64_t>();
    }
}

void do_something1(int t, ... ) {
    select_type(t, [&]<typename T> {
        process_<T>(a, b, c);
    });
}
// C++14/17 version
template<typename T>
struct type_identity {
    using type = T;
};

template<typename Lambda>
auto select_type(int t, const Lambda& l) -> decltype(l(type_identity<std::uint8_t>{})) {
    switch (t) {
        default:
        case 8 : return l(type_identity<std::uint8_t >{});
        case 16: return l(type_identity<std::uint16_t>{});
        case 32: return l(type_identity<std::uint32_t>{});
        case 64: return l(type_identity<std::uint64_t>{});
    }
}

void do_something1(int t, ... ) {
    select_type(t, [&](auto t) {
        using T = typename decltype(t)::type;
        process_<T>(a, b, c);
    });
}
bsxbgnwa

bsxbgnwa2#

我可以考虑方法指针,但我不确定如何做。
类似这样的方法应该可以奏效:

int whichOne(int t) {
    switch(t){
        default:
        case  8: return 0;
        case 16: return 1;
        case 32: return 2;
        case 64: return 3;
    }
}

struct A1{
    template<typename T>
    void process_(...){
    }

    void do_something1(int t, ...){
        using MethodType = void (A1::*)(...);
        static const MethodType methods[] = {
            &A1::process_<uint8_t >,
            &A1::process_<uint16_t>,
            &A1::process_<uint32_t>,
            &A1::process_<uint64_t>
        };
        (this->*methods[whichOne(t)])(a, b, c);
    }
};
    
struct A2{
    template<typename T>
    void process_(...){
    }

    void do_something2(int t, ...){
        using MethodType = void (A2::*)(...);
        static const MethodType methods[] = {
            &A2::process_<uint8_t >,
            &A2::process_<uint16_t>,
            &A2::process_<uint32_t>,
            &A2::process_<uint64_t>
        };
        (this->*methods[whichOne(t)])(d, e, f);
    }
};

相关问题