让我的库的用户也可以用基元值和类名调用函数



我有一个不典型的需求。我正在编写一个设置库函数,应该只使用常数值和类名来调用它。我做了这样的东西:

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; };

演示

有两个错误。

  1. setup_layers<Args...>();不向setup_layers传递任何积分模板参数。没有setup_layers的定义在第一个位置没有unsigned值模板参数,因此此调用与任何内容都不匹配。请尝试例如setup_layers<index+1, Args...>()>;

  2. 当只传递了一个类型参数时,这两个重载是不明确的。

    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

最新更新