c++ 可变参数模板,相同基数的参数后代 class
c++ variadic templates, arguments descendants of same base class
考虑以下基本接口及其两个具体实现。我想用 1 个模板方法测试这些方法,参数是要测试的类型。所有子类型(QueueA、QueueB)都继承自 IQueue。我怎样才能实现模板方法 tester_queues 的实现?通过传入 类 实例的 std::vector 可以实现类似的功能,并且会更容易。我只是好奇是否可以实现方法 tester_queues 中描述的内容。
template<class T>
class IQueue
{
protected:
T Data[10];
public:
virtual const T pop() = 0;
virtual void push(const T&) = 0;
};
template<class T>
class QueueA : public IQueue<T>
{
const T pop() final {
std::cout << "pop queue A" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue A" << std::endl;
}
};
template<class T>
class QueueB : public IQueue<T>
{
const T pop() final {
std::cout << "pop queue B" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue B" << std::endl;
}
};
template<class T>
void test_push_pop(IQueue<T>* aQueueP)
{
aQueueP->push();
aQueueP->pop();
};
template<class ... ARGS>
void tester_queues()
{
// unpack ARGS
// construct objects of each type into in a vector
// std::vector<IQueue*> vec = { ARGS... };
// then execute test_push_pop for each
// std::for_each(vec.begin(), vec.end(), [](IQueue* itemP) {
// test_push_pop(itemP);
// });
};
int main()
{
tester_queues<QueueA<int>,
QueueB<char>>();
return 0;
}
如果你真的只想指定队列类型作为模板参数,那么你可以使用类似这样的东西让tester_queues()
在内部构造这些类型的实例以进行测试:
#include <iostream>
template<class T>
class IQueue
{
protected:
T Data[10];
public:
virtual const T pop() = 0;
virtual void push(const T&) = 0;
};
template<class T>
class QueueA : public IQueue<T>
{
public:
const T pop() final {
std::cout << "pop queue A" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue A" << std::endl;
}
};
template<class T>
class QueueB : public IQueue<T>
{
public:
const T pop() final {
std::cout << "pop queue B" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue B" << std::endl;
}
};
template <class... Ts>
struct Tester;
template <class T, class... Ts>
struct Tester<T, Ts...>
{
template<class U>
static void test_push_pop(IQueue<U>&& aQueueP)
{
aQueueP.push(U{});
aQueueP.pop();
}
static void test_push_pops()
{
test_push_pop(T{});
Tester<Ts...>::test_push_pops();
}
};
template<>
struct Tester<>
{
static void test_push_pops() {}
};
template<class... Ts>
void tester_queues()
{
Tester<Ts...>::test_push_pops();
};
int main()
{
tester_queues< QueueA<int>, QueueB<char> >();
return 0;
}
或者,您可以构建自己的所需类型的对象,然后将它们作为输入参数传递给 tester_queues()
,例如:
#include <iostream>
#include <utility>
template<class T>
class IQueue
{
protected:
T Data[10];
public:
virtual const T pop() = 0;
virtual void push(const T&) = 0;
};
template<class T>
class QueueA : public IQueue<T>
{
public:
const T pop() final {
std::cout << "pop queue A" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue A" << std::endl;
}
};
template<class T>
class QueueB : public IQueue<T>
{
public:
const T pop() final {
std::cout << "pop queue B" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue B" << std::endl;
}
};
template<class T>
void test_push_pop(IQueue<T>& aQueueP)
{
aQueueP.push(T{});
aQueueP.pop();
}
void test_push_pops()
{
}
template<class T, class... Ts>
void test_push_pops(T&& aQueueP, Ts&&... aQueuePs)
{
test_push_pop(std::forward<T>(aQueueP));
test_push_pops(aQueuePs...);
};
template<class... Ts>
void tester_queues(Ts&&... args)
{
test_push_pops(args...);
};
int main()
{
tester_queues( QueueA<int>{}, QueueB<char>{} );
return 0;
}
考虑以下基本接口及其两个具体实现。我想用 1 个模板方法测试这些方法,参数是要测试的类型。所有子类型(QueueA、QueueB)都继承自 IQueue。我怎样才能实现模板方法 tester_queues 的实现?通过传入 类 实例的 std::vector 可以实现类似的功能,并且会更容易。我只是好奇是否可以实现方法 tester_queues 中描述的内容。
template<class T>
class IQueue
{
protected:
T Data[10];
public:
virtual const T pop() = 0;
virtual void push(const T&) = 0;
};
template<class T>
class QueueA : public IQueue<T>
{
const T pop() final {
std::cout << "pop queue A" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue A" << std::endl;
}
};
template<class T>
class QueueB : public IQueue<T>
{
const T pop() final {
std::cout << "pop queue B" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue B" << std::endl;
}
};
template<class T>
void test_push_pop(IQueue<T>* aQueueP)
{
aQueueP->push();
aQueueP->pop();
};
template<class ... ARGS>
void tester_queues()
{
// unpack ARGS
// construct objects of each type into in a vector
// std::vector<IQueue*> vec = { ARGS... };
// then execute test_push_pop for each
// std::for_each(vec.begin(), vec.end(), [](IQueue* itemP) {
// test_push_pop(itemP);
// });
};
int main()
{
tester_queues<QueueA<int>,
QueueB<char>>();
return 0;
}
如果你真的只想指定队列类型作为模板参数,那么你可以使用类似这样的东西让tester_queues()
在内部构造这些类型的实例以进行测试:
#include <iostream>
template<class T>
class IQueue
{
protected:
T Data[10];
public:
virtual const T pop() = 0;
virtual void push(const T&) = 0;
};
template<class T>
class QueueA : public IQueue<T>
{
public:
const T pop() final {
std::cout << "pop queue A" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue A" << std::endl;
}
};
template<class T>
class QueueB : public IQueue<T>
{
public:
const T pop() final {
std::cout << "pop queue B" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue B" << std::endl;
}
};
template <class... Ts>
struct Tester;
template <class T, class... Ts>
struct Tester<T, Ts...>
{
template<class U>
static void test_push_pop(IQueue<U>&& aQueueP)
{
aQueueP.push(U{});
aQueueP.pop();
}
static void test_push_pops()
{
test_push_pop(T{});
Tester<Ts...>::test_push_pops();
}
};
template<>
struct Tester<>
{
static void test_push_pops() {}
};
template<class... Ts>
void tester_queues()
{
Tester<Ts...>::test_push_pops();
};
int main()
{
tester_queues< QueueA<int>, QueueB<char> >();
return 0;
}
或者,您可以构建自己的所需类型的对象,然后将它们作为输入参数传递给 tester_queues()
,例如:
#include <iostream>
#include <utility>
template<class T>
class IQueue
{
protected:
T Data[10];
public:
virtual const T pop() = 0;
virtual void push(const T&) = 0;
};
template<class T>
class QueueA : public IQueue<T>
{
public:
const T pop() final {
std::cout << "pop queue A" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue A" << std::endl;
}
};
template<class T>
class QueueB : public IQueue<T>
{
public:
const T pop() final {
std::cout << "pop queue B" << std::endl;
return T{};
}
void push(const T& aItemRef) final {
std::cout << "PUSH queue B" << std::endl;
}
};
template<class T>
void test_push_pop(IQueue<T>& aQueueP)
{
aQueueP.push(T{});
aQueueP.pop();
}
void test_push_pops()
{
}
template<class T, class... Ts>
void test_push_pops(T&& aQueueP, Ts&&... aQueuePs)
{
test_push_pop(std::forward<T>(aQueueP));
test_push_pops(aQueuePs...);
};
template<class... Ts>
void tester_queues(Ts&&... args)
{
test_push_pops(args...);
};
int main()
{
tester_queues( QueueA<int>{}, QueueB<char>{} );
return 0;
}