【问题标题】:Policy classes with differing interfaces具有不同接口的策略类
【发布时间】:2015-09-16 09:31:55
【问题描述】:

假设一个算法有一个策略FooPolicy。实现此策略的策略类具有静态成员函数 foo,但对于其中一些,foo 采用 int 参数,而对于另一些则没有。我正在尝试通过constexpr 静态数据成员来启用这些具有不同接口的策略类:

struct SimpleFoo {
    static constexpr bool paramFlag = false;
    static void foo() {
        std::cout << "In SimpleFoo" << std::endl;
    }
};

struct ParamFoo {
    static constexpr bool paramFlag = true;
    static void foo(int param) {
        std::cout << "In ParamFoo " << param << std::endl;
    }
};

template <typename FooPolicy>
struct Alg {
    void foo() {
        if (FooPolicy::paramFlag) FooPolicy::foo(5);
        else FooPolicy::foo();
    }
};

int main() {
    Alg<ParamFoo> alg;
    alg.foo();
    return 0;
}

此代码无法编译。 gcc 4.8.2 报错:

没有匹配的函数调用'ParamFoo::foo()'

else FooPolicy::foo();

else 子句被编译,尽管在编译时知道FooPolicy::paramFlagtrue。有没有办法让它工作?

【问题讨论】:

  • 是的,提供两个通过例如有条件地选择的重载。标签调度
  • 你甚至可以省去国旗,只用 SFINAE 它。
  • 您不能就所有函数的int param = 0 参数达成一致?
  • 另一种方法是使用对象,而不是类型,就像标准库对其策略(比较器、哈希器、分配器)所做的那样。然后这些对象可以是有状态的。
  • @KerrekSB 从这样的简短评论中很难看出您的意思。使用对象如何处理这两个策略具有不同接口的事实?如果您将您的评论变成回复,我将不胜感激。

标签: c++ c++11 policy-based-design


【解决方案1】:

有没有办法让它工作?

一种解决方案是使用标签调度:

#include <type_traits>

template <typename FooPolicy>
struct Alg {
    void foo() {
        foo(std::integral_constant<bool, FooPolicy::paramFlag>{});
    }    
private:
    void foo(std::true_type) {
        FooPolicy::foo(5);
    }
    void foo(std::false_type) {
        FooPolicy::foo();
    }
};

DEMO

【讨论】:

    【解决方案2】:

    你可以完全放弃标志并使用表达式 SFINAE:

    template <typename FooPolicy>
    struct Alg {
        template <typename T=FooPolicy> //put FooPolicy in immediate context
        //SFINAEd out if that call is not valid
        auto foo() -> decltype(T::foo(),void()) {
            FooPolicy::foo();
        }
    
        template <typename T=FooPolicy>
        auto foo() -> decltype(T::foo(0),void()) {
            FooPolicy::foo(6);
        }
    };
    

    【讨论】:

    • 感谢您提出更好的设计建议!
    猜你喜欢
    • 2010-12-29
    • 2014-05-26
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-02
    相关资源
    最近更新 更多