简体   繁体   English

使用可变参数 arguments 的模板 function 特化

[英]template function specialization using variadic arguments

I have a class that takes a variable number of arguments (including no arguments) but when I try to pass a struct as argument for its constructor, I get a compile time error:我有一个 class ,它采用可变数量的 arguments (不包括参数),但是当我尝试将结构作为其构造函数的参数传递时,出现编译时错误:

error: converting to 'const ioPin' from initializer list would use explicit constructor 'ioPin::ioPin(Args ...) [with Args = {gpioPort, gpioMode, pinState}]'
11 | t::A, .mode = gpioMode::output, .state = pinState::high });

This is my class:这是我的 class:

/*ioPin.hh*/

struct ioPinParams
{
    gpioPort port{gpioPort::null};
    gpioPin pin{gpioPin::null};
    gpioMode mode{gpioMode::input};
    gpioPUPD pupd{gpioPUPD::disabled};
    gpioOutputType oType{gpioOutputType::pushPull};
    gpioOutputSpeed oSpeed{gpioOutputSpeed::low};
    pinState state{pinState::low};
};

class ioPin
{
    private:

    bool init();
    bool init(const GPIO_TypeDef *);
    bool init(const gpioPort &);
    bool init(const ioPinParams &);
    bool init(const gpioPin &);
    bool init(const gpioMode &);
    bool init(const gpioPUPD &);
    bool init(const gpioOutputType&);
    bool init(const gpioOutputSpeed&);
    bool init(const pinState &);

    public:
    explicit ioPin();

    template<class ...Args>
    explicit ioPin(Args ...args);
    ~ioPin();

};

template<class ...Args>
ioPin::ioPin(Args ...args)
{
    init();
    (init(args),...);
}

This is the implementation file:这是实现文件:

/*ioPin.cpp*/

#include "ioPin.hh"
ioPin::ioPin()
{
    init();
}

This is the main:这是主要的:

ioPin a; /* <--- This instantation works well */ 
ioPin b(gpioMode::output, gpioPin::_5, pinState::high, gpioPUPD::disabled, GPIOA); /* <--- This instantation works well */ 
ioPin c(GPIOA, gpioPin::_5, gpioMode::output, pinState::high); /* <--- This instantation works well */ 
ioPin d(gpioMode::output, gpioPin::_5, pinState::high, gpioPort::A); /* <--- This instantation works well */ 
ioPin e( {.port = gpioPort::A, .mode = gpioMode::output, .state = pinState::high }); /* <--- Here is where the error arises */ 

int main(void)
{
    while (1)
    {
        /* code */
    }
    return 0;
}

I tried adding a template specialization to the ioPin.hh file:我尝试向 ioPin.hh 文件添加模板专业化:

template<>
ioPin::ioPin<ioPinParams>(ioPinParams params)
{

}

But the error remains exactly the same.但是错误仍然完全相同。

If I remove the explicit specifier from the constructor, the program compiles but the method如果我从构造函数中删除显式说明符,则程序编译但方法

        bool init(const ioPinParams &):

Never gets called.永远不会被调用。

As the last resort, I though of the dumb idea of overloading the constructor like:作为最后的手段,我想到了重载构造函数的愚蠢想法,例如:

explicit ioPin(const ioPinParams &);

But then I get what is obvious: ambiguous error:但后来我得到了明显的:模棱两可的错误:

error: call of overloaded 'ioPin(<brace-enclosed initializer list>)' is ambiguous
11 | t::A, .mode = gpioMode::output, .state = pinState::high });
                                                              ^

I'd really appreciate help on this.我真的很感激这方面的帮助。 I don't know what am I missing.我不知道我错过了什么。

{.port = gpioPort::A, .mode = gpioMode::output, .state = pinState::high }

This is a braced initialization list, of some unspecified type.这是一个带括号的初始化列表,具有某种未指定的类型。 It needs to be bound to a specified type.它需要绑定到指定的类型。 This needs to specify, in some way: "Hello, I'm class X , or class Y ".这需要以某种方式指定:“您好,我是 class X或 class Y ”。

If this gets passed in as a parameter to some function that's declared as X or Y , then everything gets figured out.如果这作为参数传递给声明为XY的某些 function ,那么一切都会弄清楚。

Unfortunately, this is the only thing that your suffering C++ compiler has to work with:不幸的是,这是您遭受 C++ 编译器必须处理的唯一事情:

template<class ...Args>
explicit ioPin(Args ...args);

That's what the parameter is.这就是参数的含义。 Args , here, is also some mysterious, unspecified type, and it gets deduced to whatever the type is of the actual object that gets passed in.这里的Args也是一些神秘的、未指定的类型,它被推断为传入的实际 object 的类型。

But what gets passed in is also something that's looking to figure out what it's type is.但是传入的也是一些想要弄清楚它的类型的东西。 The TLDR version: a braced initialization list cannot be used to deduce a template parameter. TLDR 版本:大括号初始化列表不能用于推导模板参数。

You're going to have explicitly specify what this mysterious type is:您将明确指定这种神秘类型是什么:

ioPin e( ioPinParams{.port = gpioPort::A, .mode = gpioMode::output, .state = pinState::high });

This solves this Scooby-Doo mystery.这解决了这个史酷比之谜。 An ioPinParams parameter gets passed into the constructor, that's what gets deduced for the template parameter and then get forwarded to the correct initialization function via overload resolution.一个 ioPinParams 参数被传递到构造函数中,这就是模板参数的推导,然后通过重载解析转发到正确的初始化 function。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM