C++ Variadic模板空包
C++ Variadic template empty pack
我正在尝试使用具有以下签名的方法扩展 std::vector:
template<typename... An>
tuple<An...> get();
我希望它 return 向量中指定派生 class 类型的第一次出现。
但是,我在扩展空模板参数包时遇到了一些问题。我找到了这个线程:How to match empty arguments pack in variadic template 所以我修改了我的 class 现在它看起来像这样:
template<typename T>
class AggregationVector : public vector<T>
{
public:
template<typename A>
tuple<A> getSingle()
{
for (auto i = vector<T>::begin(); i != vector<T>::end(); i++)
{
A element = dynamic_cast<A>(*i);
if (element != nullptr) return make_tuple(element);
}
return make_tuple(nullptr);
}
template<typename A, typename... An>
tuple<A, An...> getHelper()
{
return tuple_cat(getSingle<A>(), get<An...>());
}
template<typename... An>
tuple<An...> get()
{
return getHelper<An...>();
}
template<>
tuple<> get<>()
{
return make_tuple();
}
};
不幸的是,我仍然遇到错误,我不知道如何解决它们:
Line 29: explicit specialization in non-namespace scope 'class AggregationVector<T>'|
Line 30: template-id 'get<>' in declaration of primary template|
In instantiation of 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {}; T = AggregationVectorTest::Base*]':|
Line 20: required from 'std::tuple<A, An ...> AggregationVector<T>::getHelper() [with A = AggregationVectorTest::DoubleDerived1*; An = {}; T = AggregationVectorTest::Base*]'|
Line 26: required from 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {AggregationVectorTest::DoubleDerived1*}; T = AggregationVectorTest::Base*]'|
Line 20: required from 'std::tuple<A, An ...> AggregationVector<T>::getHelper() [with A = AggregationVectorTest::Base*; An = {AggregationVectorTest::DoubleDerived1*}; T = AggregationVectorTest::Base*]'|
Line 26: required from 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {AggregationVectorTest::Base*, AggregationVectorTest::DoubleDerived1*}; T = AggregationVectorTest::Base*]'|
Line (this error points to line starting with "tuple<Base*, DoubleDerived1*> tup1" from example code): required from here|
Line 26: error: no matching function for call to 'AggregationVector<AggregationVectorTest::Base*>::getHelper()'|
Line 26: note: candidate is:|
Line 18: note: template<class A, class ... An> std::tuple<A, An ...> AggregationVector<T>::getHelper() [with A = A; An = {An ...}; T = AggregationVectorTest::Base*]|
Line 18: note: template argument deduction/substitution failed:|
Line 26: note: couldn't deduce template parameter 'A'|
In member function 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {}; T = AggregationVectorTest::Base*]':|
Line 27: warning: control reaches end of non-void function [-Wreturn-type]|
我知道我应该将 tuple<An... method>
的声明放在 tuple<A, An...> getHelper()
之上,但随后我收到一条错误消息,指出 get()
方法无法重载
'template<class T> template<class ... An> std::tuple<_Args1 ...> AggregationVector<T>::get()' cannot be overloaded|
with 'template<class T> template<class ... An> std::tuple<_Args1 ...> AggregationVector<T>::get()'|
下面的示例用法:
// declaration of few polymorphic classes
class Base
{
public:
int Value;
Base(int v = 0) { Value = v; }
virtual void write()
{
cout << "Base " << Value << endl;
}
virtual ~Base();
};
class Derived1 : public Base
{
public:
Derived1(int v = 0) : Base::Base(v) { }
virtual void write()
{
cout << "Derived1 " << Value << endl;
}
};
class DoubleDerived1 : public Derived1
{
public:
DoubleDerived1(int v = 0) : Derived1::Derived1(v) { }
virtual void write()
{
cout << "DoubleDerived1 " << Value << endl;
}
};
class Derived2 : public Base
{
public:
Derived2(int v = 0) : Base::Base(v) { }
virtual void write()
{
cout << "Derived2 " << Value << endl;
}
};
//test implementation
Base a1(1);
Base a2(2);
Derived1 b3(3);
DoubleDerived1 bb4(4);
Derived2 c5(5);
Derived2 c6(6);
AggregationVector<Base*> vec {&a1, &a2, &b3, &bb4, &c5, &c6};
tuple<Base*, DoubleDerived1*> tup1 = vec.get<Base*, DoubleDerived1*>();
tuple<Derived1*, DoubleDerived1*, Derived2*> tup2 = vec.get<Derived1*, DoubleDerived1*, Derived2*>();
cout << "Test Tuple1 result: " << (get<0>(tup1)->Value == 1 && get<1>(tup1)->Value == 4) << endl;
cout << "Test Tuple2 result: " << (get<0>(tup2)->Value == 3 && get<1>(tup2)->Value == 4 && get<2>(tup2)->Value == 5) << endl;
您不需要get
的任何专业化,只需要
template<typename... An>
tuple<An...> get()
{
return tuple_cat(getSingle<An>()...);
}
我正在尝试使用具有以下签名的方法扩展 std::vector:
template<typename... An>
tuple<An...> get();
我希望它 return 向量中指定派生 class 类型的第一次出现。
但是,我在扩展空模板参数包时遇到了一些问题。我找到了这个线程:How to match empty arguments pack in variadic template 所以我修改了我的 class 现在它看起来像这样:
template<typename T>
class AggregationVector : public vector<T>
{
public:
template<typename A>
tuple<A> getSingle()
{
for (auto i = vector<T>::begin(); i != vector<T>::end(); i++)
{
A element = dynamic_cast<A>(*i);
if (element != nullptr) return make_tuple(element);
}
return make_tuple(nullptr);
}
template<typename A, typename... An>
tuple<A, An...> getHelper()
{
return tuple_cat(getSingle<A>(), get<An...>());
}
template<typename... An>
tuple<An...> get()
{
return getHelper<An...>();
}
template<>
tuple<> get<>()
{
return make_tuple();
}
};
不幸的是,我仍然遇到错误,我不知道如何解决它们:
Line 29: explicit specialization in non-namespace scope 'class AggregationVector<T>'|
Line 30: template-id 'get<>' in declaration of primary template|
In instantiation of 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {}; T = AggregationVectorTest::Base*]':|
Line 20: required from 'std::tuple<A, An ...> AggregationVector<T>::getHelper() [with A = AggregationVectorTest::DoubleDerived1*; An = {}; T = AggregationVectorTest::Base*]'|
Line 26: required from 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {AggregationVectorTest::DoubleDerived1*}; T = AggregationVectorTest::Base*]'|
Line 20: required from 'std::tuple<A, An ...> AggregationVector<T>::getHelper() [with A = AggregationVectorTest::Base*; An = {AggregationVectorTest::DoubleDerived1*}; T = AggregationVectorTest::Base*]'|
Line 26: required from 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {AggregationVectorTest::Base*, AggregationVectorTest::DoubleDerived1*}; T = AggregationVectorTest::Base*]'|
Line (this error points to line starting with "tuple<Base*, DoubleDerived1*> tup1" from example code): required from here|
Line 26: error: no matching function for call to 'AggregationVector<AggregationVectorTest::Base*>::getHelper()'|
Line 26: note: candidate is:|
Line 18: note: template<class A, class ... An> std::tuple<A, An ...> AggregationVector<T>::getHelper() [with A = A; An = {An ...}; T = AggregationVectorTest::Base*]|
Line 18: note: template argument deduction/substitution failed:|
Line 26: note: couldn't deduce template parameter 'A'|
In member function 'std::tuple<_Args1 ...> AggregationVector<T>::get() [with An = {}; T = AggregationVectorTest::Base*]':|
Line 27: warning: control reaches end of non-void function [-Wreturn-type]|
我知道我应该将 tuple<An... method>
的声明放在 tuple<A, An...> getHelper()
之上,但随后我收到一条错误消息,指出 get()
方法无法重载
'template<class T> template<class ... An> std::tuple<_Args1 ...> AggregationVector<T>::get()' cannot be overloaded|
with 'template<class T> template<class ... An> std::tuple<_Args1 ...> AggregationVector<T>::get()'|
下面的示例用法:
// declaration of few polymorphic classes
class Base
{
public:
int Value;
Base(int v = 0) { Value = v; }
virtual void write()
{
cout << "Base " << Value << endl;
}
virtual ~Base();
};
class Derived1 : public Base
{
public:
Derived1(int v = 0) : Base::Base(v) { }
virtual void write()
{
cout << "Derived1 " << Value << endl;
}
};
class DoubleDerived1 : public Derived1
{
public:
DoubleDerived1(int v = 0) : Derived1::Derived1(v) { }
virtual void write()
{
cout << "DoubleDerived1 " << Value << endl;
}
};
class Derived2 : public Base
{
public:
Derived2(int v = 0) : Base::Base(v) { }
virtual void write()
{
cout << "Derived2 " << Value << endl;
}
};
//test implementation
Base a1(1);
Base a2(2);
Derived1 b3(3);
DoubleDerived1 bb4(4);
Derived2 c5(5);
Derived2 c6(6);
AggregationVector<Base*> vec {&a1, &a2, &b3, &bb4, &c5, &c6};
tuple<Base*, DoubleDerived1*> tup1 = vec.get<Base*, DoubleDerived1*>();
tuple<Derived1*, DoubleDerived1*, Derived2*> tup2 = vec.get<Derived1*, DoubleDerived1*, Derived2*>();
cout << "Test Tuple1 result: " << (get<0>(tup1)->Value == 1 && get<1>(tup1)->Value == 4) << endl;
cout << "Test Tuple2 result: " << (get<0>(tup2)->Value == 3 && get<1>(tup2)->Value == 4 && get<2>(tup2)->Value == 5) << endl;
您不需要get
的任何专业化,只需要
template<typename... An>
tuple<An...> get()
{
return tuple_cat(getSingle<An>()...);
}