我有一个不典型的需求。我正在编写一个设置库函数,应该只使用常数值和类名来调用它。我做了这样的东西:
template <unsigned index, class layerClass, typename...Args>
void setup_layers() {
//add layer
//recursively call yourself
setup_layers<Args...>();
}
template <unsigned index, class layerClass>
void setup_layers() {
//add layer
}
当我尝试使用我的功能时:
struct MyLayer {};
int main (int argc, char **argv)
{
constexpr unsigned LAYER_NUM = 0;
setup_layers<LAYER_NUM, MyLayer>();
return 0;
}
编译器报告错误call of overloaded ‘setup_layers<LAYER_NUM, MyLayer>()’ is ambiguous
我不确定如何用另一种方式来实现我的需求:(.如果我可以通过普通参数将类名作为参数传递给我的函数,那就好了,但C++没有这样的功能…
编辑好吧,这似乎是我的"解决方案";哪儿也不去,根本不起作用。因为我不想删除有答案的问题,所以也许我应该用不同的方式问我的问题:
我希望我的库的用户设置一个带有索引的层列表(其中这些索引中的数字不必有连续的数字(。我之所以想使用模板来做这件事,是因为模板只能允许常量值作为参数。简单地说:我想禁止我的用户使用变量作为索引的参数。
这里有一个解决歧义的选项:您可以重命名执行实际设置实现的函数。我称之为setup_impl
:
template <unsigned index, class layerClass>
void setup_impl() {
//add layer
std::cout << index << 'n';
}
template <unsigned index, class layerClass, class... Args>
void setup_layers() {
setup_impl<index, layerClass>();
if constexpr (sizeof...(Args) > 0) {
setup_layers<index + 1, Args...>();
}
}
演示
如果每次使用Layer类时index
都应该相同,则可以将index
作为Layer类的属性。
示例:
template <class layerClass>
void setup_impl() {
std::cout << layerClass::index << 'n';
}
template <class... Args>
void setup_layers() {
(setup_impl<Args>(), ...); // fold expression
}
struct MyLayer1 { static constexpr unsigned index = 11; };
struct MyLayer2 { static constexpr unsigned index = 22; };
struct MyLayer3 { static constexpr unsigned index = 33; };
演示
有两个错误。
-
setup_layers<Args...>();
不向setup_layers
传递任何积分模板参数。没有setup_layers
的定义在第一个位置没有unsigned
值模板参数,因此此调用与任何内容都不匹配。请尝试例如setup_layers<index+1, Args...>()>;
。 -
当只传递了一个类型参数时,这两个重载是不明确的。
template <unsigned index, class layerClass, typename...Args> ... template <unsigned index, class layerClass /*, nothing */> ...
空的
typename ... Args
包是合法的,没有理由喜欢空的参数包而不是什么都不喜欢,反之亦然。尝试从第二个过载中删除class layerClass
(并让它什么都不做(。template <unsigned index> void setup_layers() {}
应该可以。
你可以这样做:
#include <iostream>
#include <typeinfo>
template <int index, class layerClass>
void setup_layers(int layer) {
//add layer
std::cout << "Adding layer " << layer << ": " << typeid(layerClass).name() << std::endl;
}
template <class layerClass, typename...Args>
void setup_layers(int layer) {
//add layer
//recursively call yourself
if constexpr (sizeof...(Args) > 0) {
setup_layers<0, layerClass>(++layer);
setup_layers<Args...>(layer);
} else {
setup_layers<0, layerClass>(layer);
}
}
struct MyLayer {};
struct OtherLayer {};
int main() {
setup_layers<MyLayer, OtherLayer, MyLayer, OtherLayer>(0);
std::cout << "End" << std::endl;
}
输出:
Adding layer 1: 7MyLayer
Adding layer 2: 10OtherLayer
Adding layer 3: 7MyLayer
Adding layer 3: 10OtherLayer
End