传递可变参数模板参数时出现视觉工作室错误

Visual studio error when relaying variadic template parameters

本文关键字:参数 视觉 错误 工作室 变参      更新时间:2023-10-16

我有一个模板函数,其中包含可变数量的模板参数,这些参数被"中继"到std::function参数:

template<typename... Args>
    void test1(const std::function<void(Args...)> &function)
{}
static void t(float) {}
int main(int argc,char *argv[])
{
    test1<float>(nullptr);
    test1<float>(&t);
    test1<float>([](float f) -> void {
    });
    return EXIT_SUCCESS;
}

这编译并运行良好,但Visual Studio以红色在main中为所有test1调用加下划线,并显示以下错误消息:

template<class... Args> void test1(const std::function<void(Args...)> &function)
no instance of function template "test1" matches the argument list
    argument types are: (lambda []void(float f)->void)

另一方面,这不会显示为错误:

template<typename... Args>
    void test2(Args... a)
{}
int main(int argc,char *argv[])
{
    test2<float>(1.f);
    return EXIT_SUCCESS;
}

我是否对第一种情况做了不正确的操作,或者这是误报?这只是Visual Studio本身的错误,编译器甚至不会抛出任何警告。

//编辑:

我刚刚用 g++-5 在 Linux 上做了一些测试,它根本不让我编译代码:

root@******:/var/projects# g++-5 -std=c++1y test.cpp
test.cpp: In function ‘int main(int, char**)’:
test.cpp:12:22: error: no matching function for call to ‘test1(std::nullptr_t)’
  test1<float>(nullptr);
                      ^
test.cpp:5:7: note: candidate: template<class ... Args> void test1(const std::function<void(Args ...)>&)
  void test1(const std::function<void(Args...)> &function)
       ^
test.cpp:5:7: note:   template argument deduction/substitution failed:
test.cpp:12:22: note:   mismatched types ‘const std::function<void(Args ...)>’ and ‘std::nullptr_t’
  test1<float>(nullptr);
                      ^
test.cpp:13:17: error: no matching function for call to ‘test1(void (*)(float))’
  test1<float>(&t);
                 ^
test.cpp:5:7: note: candidate: template<class ... Args> void test1(const std::function<void(Args ...)>&)
  void test1(const std::function<void(Args...)> &function)
       ^
test.cpp:5:7: note:   template argument deduction/substitution failed:
test.cpp:13:17: note:   mismatched types ‘const std::function<void(Args ...)>’ and ‘void (*)(float)’
  test1<float>(&t);
                 ^
test.cpp:16:3: error: no matching function for call to ‘test1(main(int, char**)::<lambda(float)>)’
  });
   ^
test.cpp:5:7: note: candidate: template<class ... Args> void test1(const std::function<void(Args ...)>&)
  void test1(const std::function<void(Args...)> &function)
       ^
test.cpp:5:7: note:   template argument deduction/substitution failed:
test.cpp:16:3: note:   ‘main(int, char**)::<lambda(float)>’ is not derived from ‘const std::function<void(Args ...)>’
  });
   ^

要解决问题并使程序按预期工作,您可以将测试函数包装在模板结构中:

template<typename... Args>
struct foo {
   static void test1(const std::function<void(Args...)> &function) {}
};

并称之为:

foo<float>::test1(nullptr);
foo<float>::test1(&t);
foo<float>::test1([](float f) -> void {
});

它肯定会防止你的Args...被推断出来。

Visual Studio 解析有点落后于编译器,并且是单独实现的。可变参数模板对于Visual Studio来说仍然很新,所以它可能是一个已知的限制/错误。

更新:

即使使用最新版本的 clang,我也不清楚发生了什么:实时示例,因为您确实将Args...修复为"float",但相应的非模板代码确实可以编译。

此外,如果您将Args...更改为Args它确实有效。我不清楚为什么...

更新2:我发现你的问题是一个重复的问题,有一个很好的答案:标准::函数中的可变参数模板参数匹配

草率的总结:当你写test2<float>它或多或少意味着test2<float,Args...>,这阻碍了进一步的转换。