Variadic Template Specialization Overload 在 GCC 中有效,但在 MSVC 中无效

Variadic Template Specialization Overload works in GCC but not MSVC

我有以下函数声明

    template<typename RET, typename... PARAMS>
    RET Execute(PARAMS... params)
    { ... }
    
    template<typename RET>
    RET Execute()
    { ... }

    template<typename... PARAMS>
    void Execute(PARAMS... params)
    { ... }

    void Execute();

这些调用在 GCC 和 MSVC 中都能正常工作

    Execute<int32_t>(static_cast<int8_t>(0), static_cast<int32_t>(0))
    Execute<int32_t>()
    Execute(static_cast<uint8_t>(0))
    Execute()

这个调用在 GCC 中工作正常,但在 MSVC 中不行。对重载函数的模糊调用出现错误。只是因为 return 类型与第一个参数相同。

    Execute<int32_t>(static_cast<int32_t>(0), static_cast<int32_t>(0))

考虑到无法明确给出参数包的类型名称,这并没有歧义。为什么 MSVC 似乎有这个错误?有办法解决这个问题吗?

This call works fine in GCC, but not in MSVC.

在我的 Debian 稳定版中,clang++ 11.0.1-2(“错误:对 'Execute' 的调用不明确”)和 g++ 10.2.1(“错误:调用重载'执行(int32_t, int32_t)'是不明确的").

Considering it is not possible to explicitly give the typenames of the parameter pack

不完全是:您可以显式指定参数的类型名称或第一个参数的类型;这允许覆盖从参数中推导的类型名。

Why does MSVC seem to have this wrong?

我的问题是:为什么你的 g++ 似乎有这个权利?

Is there anyway to fix this?

是的,一个非常简单的方法:在参数类型的可变参数列表之前添加一个 non-types 模板参数的可变参数列表。

我的意思是,写第三个Execute()如下

template <int..., typename... PARAMS>
void Execute (PARAMS... params)
{ /* ... */ }

也许还有第一个如下

template <typename RET, int..., typename... PARAMS>
RET Execute (PARAMS... params)
{ /* ... */ }

通过这种方式,您可以从 params 中强加 PARAMS 类型推导,显式模板参数必须是 return 类型(当您可以表达它时)。