template<typename FilterComponent, typename ...FilterComponents>
std::bitset<components_count> component_impl(std::bitset<components_count> &b){
b.set(FilterComponent::get_id());
return component_impl<FilterComponents...>(b); //ambiguous
}
template<typename FilterComponent>
std::bitset<components_count> component_impl(std::bitset<components_count> &b){
b.set(FilterComponent::get_id());
return b;
}
template<typename ...FilterComponents>
std::bitset<components_count> component_mask(){
std::bitset<components_count> b;
component_impl<FilterComponents...>(b);
return b;
}
为什么这个函数调用不明确?我想把它称为component_mask<Foo,Bar,Baz>();
error: call to member function 'component_impl' is ambiguous
return component_impl<FilterComponents...>(b);
答案 0 :(得分:5)
当FilterComponents...
为空或只有一个元素时,存在歧义,因为两个函数模板同样可行。您可以向第一个模板声明添加第二个模板参数以解决歧义(如R Sahu那样)。您还可以将参数解压缩到初始化列表中以获得相同的效果:
template<typename... FilterComponents>
std::bitset<components_count> component_impl(std::bitset<components_count>& b)
{
using discard = int[];
(void)discard{ 0, (b.set(FilterComponents::get()), void(), 0)... };
return b;
}
第一个0
和尾随0
用于补偿空参数包并用整数填充列表,从而丢弃void()
类型。 void()
“删除”set()
的返回值,从而阻止可能使用其返回类型的重载operator,()
(我们知道std::bitset::set()
没有,但是当你处理一般情况时,使用它会很有帮助。)
这也消除了第二次重载以帮助递归的需要。
答案 1 :(得分:2)
当使用一个类型名称调用component_impl
时,它是不明确的。第一个版本与空的typename包匹配。第二个版本也是匹配。
将可变参数模板版本更改为在typename包之前有两个类型名称。这将消除这两个功能的歧义。
template<typename FilterComponent1, typename FilterComponent2, typename ...FilterComponents>
std::bitset<components_count> component_impl(std::bitset<components_count> &b){
b.set(FilterComponent1::get_id());
return component_impl<FilterComponent2, FilterComponents...>(b);
}