可变参数模板类遍历类型

时间:2019-02-24 02:05:15

标签: c++ templates variadic-templates

我正在尝试使用一种方法来创建可变参数模板类,该方法需要遍历模板参数并针对每种类型调用不相关的模板函数。

这个想法是使用特定的模板参数扩展此模板化类,以封装基本行为。

这个(可怕的)Checker类是一个大致概念的简单示例:

class Arg {
    Arg() {};
    virtual ~Arg() = default;
};

class A : public Arg{ /* ... */ };
class B : public Arg{ /* ... */ };
class C : public Arg{ /* ... */ };

template <typename ... SubClasses>
class Checker {
public:

    Checker() {};
    virtual ~Checker() = default;

    bool isOneOf(Arg* base) const;
};


template <typename ... SubClasses>
bool Checker<SubClasses>::isOneOf(Arg* arg) const
{
    // NOTE: I don't know how I would iterate over the class types....
    for (auto SubClass : SubClasses...) { // <-- not valid code
        if (std::dynamic_cast<SubClass>(arg)) {
            return true;
        }
    }
    return false;
}

class Whatever : public Checker<A, B> {};

auto whatever = new Whatever();
auto a = new A();
auto b = new B();
auto c = new C();

whatever->isOneOf(a); // true
whatever->isOneOf(b); // true
whatever->isOneOf(c); // false

为了使isOneOf工作,它必须能够遍历模板参数

我使用的是C ++ 14编译器,不能使用boost

3 个答案:

答案 0 :(得分:2)

我想可能的C ++ 14解决方案(也是C ++ 11)是

template <typename ... SubClasses>
bool Checker<SubClasses...>::isOneOf (Arg * arg) const
 {
   using unused = bool[];

   bool ret { false };

   (void)unused { false, ret |= (nullptr != dynamic_cast<SubClasses *>(arg))... };

   return ret;
 }

不幸的是,当第一个测试为true时,所有的nullptr != dynamic_cast测试都得到评估(如果编译器没有对其进行优化)。

如果您可以使用C ++ 17,那么使用模板折叠就更简单了

template <typename ... SubClasses>
bool Checker<SubClasses...>::isOneOf (Arg * arg) const
 { return (... || (nullptr != dynamic_cast<SubClasses *>(arg)) ); }

答案 1 :(得分:1)

android:configChanges

现在:

Caution: Handling the configuration change yourself can make it much more difficult to 
use alternative resources, because the system does not automatically apply them for you. This technique should be considered a last resort when you must avoid restarts due to a configuration change and is not recommended for most applications.

答案 2 :(得分:0)

使用C ++ 17,应该可以对折叠表达式进行修补,并一口气完成它。但是,对于C ++ 14,可能最易读,甚至不是最简洁的方法是使用帮助程序模板类,以及一些专门知识...

#include <iostream>

class Arg {

public:
    Arg() {};
    virtual ~Arg() = default;
};

template<typename ...Args> struct is_one_of_helper;

template<>
struct is_one_of_helper<> {

    static bool isOneOf(Arg *arg)
    {
        return false;
    }
};

template<typename A, typename ...Args>
struct is_one_of_helper<A, Args...> {

    static bool isOneOf(Arg *arg)
    {
        if (dynamic_cast<A *>(arg))
            return true;

        return is_one_of_helper<Args...>::isOneOf(arg);
    }
};

template <typename ... SubClasses>
class Checker {
public:

    Checker() {};
    virtual ~Checker() = default;

    bool isOneOf(Arg* base) const
    {
        return is_one_of_helper<SubClasses...>::isOneOf(base);
    }
};

class A : public Arg{ /* ... */ };
class B : public Arg{ /* ... */ };
class C : public Arg{ /* ... */ };

int main()
{
    Arg *a=new A;
    Arg *b=new B;
    Arg *c=new C;

    Checker<B, C> checker;

    std::cout << checker.isOneOf(a)
          << std::endl;

    std::cout << checker.isOneOf(b)
          << std::endl;

    std::cout << checker.isOneOf(c)
          << std::endl;
}

结果输出:

0
1
1