在可变参数模板函数内使用模板类的可变参数模板方法

时间:2019-10-02 15:04:01

标签: c++ c++11 templates variadic-templates variadic-functions

以下代码不会在intel或gcc中编译。问题的症结在于,在编译器的第一遍中,使用参数包扩展调用的模板类的静态方法可变参数模板被认为是错误的语法。

template<typename T>
class foo
{
public:
    template <bool do_other_thing_too, typename... ArgTypes>
    static T doThing(ArgTypes... args)
    {
        std::vector<T> outs = { args... };
        T out = 0;
        for (auto V : outs) out += V;
        // the actual code involves templates using SFINAE, and so must either
        // be in this template's parameters or be copied, once for each value 
        // of the bool
        if (do_other_thing_too)
        {
            out *= 1.5;
        }
        return out;
    }
};

struct bar
{
    int data = 3;
    template<bool do_other_thing_too = true, typename T, typename...ArgTypes>
    T& doThings(T& out, ArgTypes... args)
    {
        //the line of the code causing the problem
        out = foo<T>::doThing<do_other_thing_too>(data, args...);
        return out;
    }
};

int main()
{
    bar george;
    int a = 0;
    george.doThings(a, 12, 10.4, 3.2f, 4ll, 2l);
    return 0;
}

它在gcc中给出以下错误:

Test.cpp:27:61: error: expected ')' before '...' token
         out = foo<T>::doThing<do_other_thing_too>(data, args...);
                                                             ^
Test.cpp:27:65: error: parameter packs not expanded with '...':
         out = foo<T>::doThing<do_other_thing_too>(data, args...);
                                                                 ^
Test.cpp:27:65: note:         'args'

我已经对代码进行了一些摆弄,如果将foo的T参数折叠到foo :: doThing的模板中,也不会发生这种情况。

class foo
{
public:
    template <typename T, bool do_other_thing_too, typename... ArgTypes>
    static T doThing(ArgTypes... args)

此外,直接调用foo<int>::doThing<true>(3, 12, 10.4, 3.2f, 4ll, 2l)也没有问题,但是在产生此代码的代码中都没有可用的选项。 我有一个短期解决问题的方法,do_other_thing_too可以是bar中的模板参数,可以通过值传递给foo,然后可以/是否可以将其推回到实际需要的模板中,但是那有点丑陋,我真的很想知道实际上是什么引起了这个问题。

与TLDR相关的TLDR: 模板语法可能不明确

foo<T>::doThing<do_other_thing_too>(data, args...);

可能引用的值doThing小于do_other_thing_too,但是如果将其更改为

foo<T>::template doThing<do_other_thing_too>(data, args...);

它知道它是一个函数

0 个答案:

没有答案