对可变参数使用声明.如何选择正确的功能

Using declaration on variadic args. How to choose the correct function?

本文关键字:选择 功能 何选择 参数 变参 声明      更新时间:2023-10-16

我有一个基于策略的设计,其中在一些策略中定义了一些函数foo(),但在其他策略中没有定义。基类总是继承自某个名为AlwaysBase的类,该类具有较差的foo()函数。

我想这样做,如果;"更好";foo()存在(策略类中的一个(,将始终选择一个。

这里有一些代码:

// logic for determining if a class has a member function (not really related)
template <class> struct sfinae_true: std::true_type{};
template <class T> static auto test_foo(int) -> sfinae_true<decltype(std::declval<T>().foo())>;
template <class> static auto test_foo(long) -> std::false_type;
template <class T> struct has_foo : decltype(test_foo<T>(0)){};
class AlwaysBase{ public: void foo(){ cout << "in AlwaysBase foo()" << endl; } };
class BPolicy{};
class CPolicy{ public: void foo(){ cout << "in Cpolicy foo()" << endl; } };
template<typename T, typename ...Args>
class A: public T, public A<Args...>
{
public:
using std::conditional_t<has_foo<T>::value, T, AlwaysBase>::foo;
};
template<typename T>
class A<T>: public T, public AlwaysBase
{
public:
using std::conditional_t<has_foo<T>::value, T, AlwaysBase>::foo;
};
int main()
{
A<BPolicy> b;
b.foo();     // outputs: In AlwaysBase foo()
A<CPolicy> c;
c.foo();     // outputs: In CPolicy foo()

A<CPolicy, BPolicy> cb;
cb.foo();    // outputs: In CPolicy foo()
A<BPolicy, CPolicy> bc;
bc.foo();    // outputs: In AlwaysBase foo() // I WANT THIS TO OUTPUT!!!!: In CPolicy foo
}

我理解这里发生的事情,当BPolicy是第一个时,using语句首先在variadic args类中使用,并隐藏在终止基类(即CPolicy::foo(中找到的任何前面的using语句。

我希望在指定策略时,顺序无关紧要,如果策略有一个行列式,则应始终首先选择该行列式,而不是AlwaysBase::foo

使用递归。如果允许空列表,这很容易:

// recursive invariant: As<Ts...>::foo is always the foo from the first capable Ts or from AlwaysBase
template<typename... Ts>
class A : public AlwaysBase { // template<> class A<>
public:
// there are no capable Ts
using AlwaysBase::foo;
};
template<typename T, typename... Ts>
class A<T, Ts...> : public T, public A<Ts...> {
public:
// from the A<Ts...> superclass, not AlwaysBase
// try to use T, fall back to Ts, and only then fall back to AlwaysBase
using std::conditional_t<has_foo<T>::value, T, A<Ts...>>::foo;
};

限制到非空列表有点烦人:

template<typename T, typename... Ts>
class A : public T, public A<Ts...> {
public:
using std::conditional_t<has_foo<T>::value, T, A<Ts...>>::foo;
};
template<typename T>
class A<T> : public T, public AlwaysBase {
public:
using std::conditional_t<has_foo<T>::value, T, AlwaysBase>::foo;
};

不过,秩序仍然很重要。如果两个策略提供foo,则第一个策略获胜。