mardi 29 août 2017

Template parameter pack deduction when not passed as last parameter

Consider the following code:

#include <iostream>
#include <functional>

template<typename... Args>
void testfunc(const std::function<void (float, Args..., char)>& func)
{

}

int main(int argc, char* argv[])
{
    auto func = [](float, int, char) {};
    auto sfunc = static_cast<std::function<void (float, int, char)>>(func);
    testfunc<int>(sfunc);

    return 0;
}

I specify the type explicitly because (http://ift.tt/2x2dd3F):

When a parameter pack doesn't appear last in the parameter declaration, it is a non-deduced context. A non-deduced context means that the template arguments have to be given explicitly.

MSVC successfully compiles it, while both gcc and clang reject the code:

source_file.cpp: In function ‘int main(int, char**)’:
source_file.cpp:14:24: error: no matching function for call to ‘testfunc(std::function<void(float, int, char)>&)’
     testfunc<int>(sfunc);
                        ^
source_file.cpp:5:6: note: candidate: template<class ... Args> void testfunc(const std::function<void(float, Args ..., char)>&)
 void testfunc(const std::function<void (float, Args..., char)>& func)
      ^
source_file.cpp:5:6: note:   template argument deduction/substitution failed:
source_file.cpp:14:24: note:   mismatched types ‘char’ and ‘int’
     testfunc<int>(sfunc);
                        ^
source_file.cpp:14:24: note:   ‘std::function<void(float, int, char)>’ is not derived from ‘const std::function<void(float, Args ..., char)>’

Let's now make a slight change - let's remove the int argument from our local func, thereby causing the template argument pack to become empty:

#include <iostream>
#include <functional>

template<typename... Args>
void testfunc(const std::function<void (float, Args..., char)>& func)
{

}

int main(int argc, char* argv[])
{
    auto func = [](float, char) {};
    auto sfunc = static_cast<std::function<void (float, char)>>(func);
    testfunc<>(sfunc);

    return 0;
}

This time, all three compilers reject the code as incorrect. Tested with http://ift.tt/2sx4KA5 and a local Visual Studio installation.

Questions:

  1. Who is correct in the first case?
  2. How to achieve the desired effect - i.e., how can I explicitly specify a (possibly empty) parameter pack?

Aucun commentaire:

Enregistrer un commentaire