samedi 28 novembre 2020

Compile error using variadic templates multiple times as arguments with VS 2019.27

Basic information

  • source code is below this text.
  • compiles with nearly every compiler not older than 5 years (gcc 6, ...)
  • compiles NOT with MS VC up to MS VC 2019 16.27
  • looks like there's a problem using a variadic template as a argument prototype of a function pointer more than once.

Questions:

  • code wrong or compiler wrong??
  • any possibility to write this more elegant and more standard conform so MS VS compiles it?
  • output at the end of the code is from compiler explorer.
#include <iostream>

// https://godbolt.org/
// https://www.onlinegdb.com/online_c++_compiler
// http://cpp.sh/

using std::ostream;
using uint = unsigned int;

template <typename... Ts> 
uint  Start (const char* String,
             void      (*fn1) (Ts...),           // Works fine with every compiler 
             Ts&&...     args)
{
    std::cout << String << ' ' << __FUNCTION__ << '\n';
    if (fn1) fn1 (args...);
    return 1;
}
template <typename... Ts> 
uint  Start (const char* String,
             void      (*fn1) (Ts...),
             void      (*fn2) (Ts...),  // Microsoft-Compiler makes trouble here using Ts a second time... ***
             Ts&&...     args)
{
    std::cout << String << ' ' << __FUNCTION__ << '\n';
    if (fn1) fn1 (args...);
    if (fn2) fn2 (args...);
    return 2;
}
template <typename... Ts> 
uint  Start (const char* String,
             void      (*fn1) (Ts...),
             void      (*fn2) (Ts...),
             void      (*fn3) (Ts...),
             Ts&&...     args)
{
    std::cout << String << ' ' << __FUNCTION__ << '\n';
    if (fn1) fn1 (args...);
    if (fn2) fn2 (args...);
    if (fn3) fn3 (args...);
    return 3;
}

void Fn1 (double x)        { std::cout << __FUNCTION__ << ' ' << 1*x << '\n'; }
void Fn2 (double x)        { std::cout << __FUNCTION__ << ' ' << 2*x << '\n'; }
void Fn3 (double x)        { std::cout << __FUNCTION__ << ' ' << 3*x << '\n'; }

void Gn1 (double x, int y) { std::cout << __FUNCTION__ << ' ' << 1*x << ' ' << 1*y << '\n'; }
void Gn2 (double x, int y) { std::cout << __FUNCTION__ << ' ' << 2*x << ' ' << 2*y << '\n'; }
void Gn3 (double x, int y) { std::cout << __FUNCTION__ << ' ' << 3*x << ' ' << 3*y << '\n'; }

int
main()
{
    std::cout << __FUNCTION__ << '\n';
    
    std::cout << Start <double>      ("Test 1" , Fn1, 12.34) << " returned\n";

    std::cout << Start <double>      ("Test 2" , Fn1, Fn2, 12.34) << " returned\n";
    
    std::cout << Start <double>      ("Test 3a", Fn1, Fn2, Fn3, 12.34) << " returned\n"; 

    std::cout << Start <double, int> ("Test 3b", Gn1, Gn2, Gn3, 12.34, 42) << " returned\n"; 
    
    std::cout << Start <double, int> ("Test 3c", 
                                      *[] (double x, int y) -> void { std::cout << __FUNCTION__ << ' ' << 1*x << ' ' << 1*y << '\n'; }, 
                                      *[] (double x, int y) -> void { std::cout << __FUNCTION__ << ' ' << 2*x << ' ' << 2*y << '\n'; }, 
                                      *[] (double x, int y) -> void { std::cout << __FUNCTION__ << ' ' << 3*x << ' ' << 3*y << '\n'; }, 
                                      3.14159, 42) << " returned\n";
    return 0;
}

/* 

x64 msvc v19.27

exxample.cpp
<source>(59): error C2660: 'Start': function does not take 4 arguments
<source>(11): note: see declaration of 'Start'
<source>(61): error C2672: 'Start': no matching overloaded function found
<source>(61): error C2782: 'uint Start(const char *,void (__cdecl *)(Ts...),Ts &&...)': template parameter 'Ts' is ambiguous
<source>(11): note: see declaration of 'Start'
<source>(61): note: could be 'double'
<source>(61): note: or       'void(__cdecl &)(double), double'
<source>(63): error C2660: 'Start': function does not take 6 arguments
<source>(11): note: see declaration of 'Start'
<source>(66): error C2593: 'operator *' is ambiguous
<source>(66): note: could be 'built-in C++ operator*(main::<lambda_00de9a703c525e1d30b87861a11e038f>::<lambda_typedef_cdecl>)'
<source>(66): note: or       'built-in C++ operator*(main::<lambda_00de9a703c525e1d30b87861a11e038f>::<lambda_typedef_vectorcall>)'
<source>(66): note: while trying to match the argument list '(main::<lambda_00de9a703c525e1d30b87861a11e038f>)'
<source>(66): error C2100: illegal indirection
<source>(67): error C2593: 'operator *' is ambiguous
<source>(67): note: could be 'built-in C++ operator*(main::<lambda_63e8d9ca3695b55d9d6dc9dda05048f3>::<lambda_typedef_cdecl>)'
<source>(67): note: or       'built-in C++ operator*(main::<lambda_63e8d9ca3695b55d9d6dc9dda05048f3>::<lambda_typedef_vectorcall>)'
<source>(67): note: while trying to match the argument list '(main::<lambda_63e8d9ca3695b55d9d6dc9dda05048f3>)'
<source>(67): error C2100: illegal indirection
<source>(68): error C2593: 'operator *' is ambiguous
<source>(68): note: could be 'built-in C++ operator*(main::<lambda_9769e2f1b0b076d22151082820474129>::<lambda_typedef_cdecl>)'
<source>(68): note: or       'built-in C++ operator*(main::<lambda_9769e2f1b0b076d22151082820474129>::<lambda_typedef_vectorcall>)'
<source>(68): note: while trying to match the argument list '(main::<lambda_9769e2f1b0b076d22151082820474129>)'
<source>(68): error C2100: illegal indirection
Compiler returned: 2

*/

Aucun commentaire:

Enregistrer un commentaire