c++ - 如何防止为未实现方法的对象生成模板

标签 c++ templates methods lambda metaprogramming

为了示例的目的,假设我有 3 个简单的 struct,其中第二个不包含 bar 方法:

struct one {
    void foo(const int);
    void bar();
};

struct two {
    void foo(const int);
};

struct three {
    void foo(const int);
    void bar();
};

然后我有一个 struct 将管理这些类型的对象:

struct owner {
    map<int, one> ones;
    map<int, two> twos;
    map<int, three> threes;

    template <typename T, typename Func>
    void callFunc(T& param, const Func& func) {
        func(param);
    }

    template <typename T>
    void findObject(int key, const T& func) {
        if(ones.count(key) != 0U) {
            callFunc(ones[key], func);
        } else if(twos.count(key) != 0U) {
            callFunc(twos[key], func);
        } else {
            callFunc(threes[key], func);
        }
    }

    void foo(const int key, const int param) { findObject(key, [&](auto& value) { value.foo(param); } ); }
    void bar(const int key) { findObject(key, [&](auto& value) { value.bar(); } ); }
};

当我尝试编译它时,我得到:

error: struct two has no member named bar

有什么办法可以解决这个问题吗?

Live Example

最佳答案

首先,实用程序。一个是我们最喜欢的 overload,它展示了三个 C++17 特性,并在两行中​​重载了几个函数对象的 operator()

template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
template<class... Ts> overload(Ts...) -> overload<Ts...>;

然后是一个接受一切的后备标签类型:

struct fallback_t { template<class T> fallback_t(T&&) {} };

现在开始调用本身。我们通过将 value.bar() 调用放入尾随返回类型,然后使用回退重载重载它,如果实际调用它具有未定义的行为(因为 OP“省略[ted] 任何明确的行为定义"):

void bar(const int key) { 
    findObject(key, overload {
          [&](auto& value) -> decltype(void(value.bar())) { value.bar(); },
          [](fallback_t){ fire_missiles_and_impregnate_cat(); }
    } ); 
}

关于c++ - 如何防止为未实现方法的对象生成模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48835628/

相关文章:

java - 将单独类的方法调用到另一个类中

c++ - 如何读取用 std::ofstream 保存的 OpenCV 矩阵数据?

c++ - 部分模板模板 vector 特化

c++ - 如何使类成员变量与函数模板的返回类型相同?

c++ - :C++: Exposing specialized templates only

c# - 将多个 SqlParameter 传递给方法

PHP静态方法递归

c++ - 嵌套局部类的静态方法

c++ - 并非为所有类生成文档

c++ - Linux gcc 选择尝试实例化函数应该在的模板