You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无参模板函数重载解析的C++20合规性与歧义判定咨询

C++20模板函数重载解析:合法性与歧义判定

在测试模板函数的重载解析时,我发现Clang 15、GCC 12.2、MSVC 19.33等主流C编译器的处理结果存在差异。由于对函数模板重载的细节了解不足,现明确咨询:以下各命名空间中的函数重载,哪些属于合法的C20代码?哪些会触发重载歧义?


一、省略号相关重载(ellipsis)

#e1 | Clang: 通过 | GCC: 歧义 | MSVC: 歧义(主干版本:通过)

namespace e1 {
    template<typename...>
    void f(...);

    template<typename... Ts>
    void f(Ts...);
}

#e2 | Clang: 通过 | GCC: 歧义 | MSVC: 歧义(主干版本:通过)

namespace e2 {
    template<typename...>
    void f(...);

    template<typename..., typename... Ts>
    void f(Ts...);
}

#e3 | Clang: 通过 | GCC: 歧义 | MSVC: 非法且歧义(主干版本:非法)

namespace e3 {
    template<typename...>
    void f(...);

    template<typename... Ts, typename...>
    void f(Ts...);
}

#e4 | Clang: 通过 | GCC: 歧义 | MSVC: 非法且歧义(主干版本:非法)

namespace e4 {
    template<typename..., typename...>
    void f(...);

    template<typename... Ts>
    void f(Ts...);
}

#e5 | Clang: 歧义 | GCC: 歧义 | MSVC: 歧义(主干版本:通过)

namespace e5 {
    template<typename... Ts>
    void f(Ts..., ...);

    template<typename... Ts>
    void f(Ts...);
}

#e6 | Clang: 通过 | GCC: 歧义 | MSVC: 歧义

namespace e6 {
    template<typename... Ts>
    void f(Ts..., ...);

    template<typename...>
    void f(...);
}

二、默认参数相关重载(defaulted argument)

#d1 | Clang: 通过(主干版本:歧义) | GCC: 通过 | MSVC: 歧义(主干版本:通过)

namespace d1 {
    template<typename...>
    void f(bool = true);

    template<typename... Ts>
    void f(Ts...);
}

#d2 | Clang: 通过(主干版本:歧义) | GCC: 通过 | MSVC: 非法且歧义(主干版本:非法)

namespace d2 {
    template<typename...>
    void f(bool = true);

    template<typename... Ts, typename...>
    void f(Ts...);
}

#d3 | Clang: 通过(主干版本:歧义) | GCC: 通过 | MSVC: 歧义(主干版本:通过)

namespace d3 {
    template<typename...>
    void f(bool = true);

    template<typename..., typename... Ts>
    void f(Ts...);
}

#d4 | Clang: 歧义(主干版本:通过) | GCC: 通过 | MSVC: 通过

namespace d4 {
    template<typename...>
    void f(bool = true);

    template<typename... Ts, typename... Us>
    void f(Ts..., Us...);
}

#d5 | Clang: 歧义 | GCC: 通过 | MSVC: 非法

namespace d5 {
    template<typename...>
    void f(bool = true);

    template<typename... Ts, typename...>
    void f(Ts..., ...);
}

#d6 | Clang: 通过(主干版本:歧义) | GCC: 通过 | MSVC: 非法且歧义(主干版本:非法且歧义)

namespace d6 {
    template<typename...>
    void f(bool = true);

    template<typename..., typename... Ts>
    void f(Ts..., ...);
}

#d7 | Clang: 通过 | GCC: 歧义 | MSVC: 通过

namespace d7 {
    template<typename...>
    void f(bool = true);

    template<typename... Ts>
    void f(bool = true, Ts...);
}

#d8 | Clang: 通过 | GCC: 歧义 | MSVC: 歧义(主干版本:通过)

namespace d8 {
    template<typename...>
    void f(bool = true, ...);

    template<typename... Ts>
    void f(bool = true, Ts...);
}

测试结果概览

测试用例Clang 15Clang 主干版本GCC 12.2GCC 主干版本MSVC 19.33MSVC 主干版本
#e1通过通过歧义歧义歧义通过
#e2通过通过歧义歧义歧义通过
#e3通过通过歧义歧义非法且歧义非法
#e4通过通过歧义歧义非法且歧义非法
#e5歧义歧义歧义歧义歧义通过
#e6通过通过歧义歧义歧义通过
#d1通过歧义通过通过歧义通过
#d2通过歧义通过通过非法且歧义非法
#d3通过歧义通过通过歧义通过
#d4歧义通过通过通过通过通过
#d5歧义歧义通过通过非法非法
#d6通过歧义通过通过非法且歧义非法且歧义
#d7通过通过歧义歧义通过通过
#d8通过通过歧义歧义歧义通过

错误信息示例

Clang 15 在测试用例 d4 中的错误:

<source>:135:28: error: call to 'f' is ambiguous
static_assert(not noexcept(f()));
                           ^
<source>:89:10: note: candidate function [with $0 = <>]
    void f(bool = true);
         ^
<source>:92:10: note: candidate function [with Ts = <>, Us = <>]
    void f(Ts..., Us...);
         ^

GCC 12.2 在测试用例 d7 中的错误:

<source>:135:29: error: call of overloaded 'f()' is ambiguous
  135 | static_assert(not noexcept(f()));
      |                            ~^~
<source>:116:10: note: candidate: 'void d7::f(bool)
                 [with <template-parameter-1-1> = {}]'
  116 |     void f(bool = true);
      |          ^
<source>:119:10: note: candidate: 'void d7::f(bool, Ts ...) [with Ts = {}]'
  119 |     void f(bool = true, Ts...);
      |          ^

MSVC 19.33 在测试用例 e3 中的错误:

<source>(27): error C3547: template parameter '<unnamed-symbol>' cannot be used
              because it follows a template parameter pack and cannot be deduced
              from the function parameters of 'e3::f'
<source>(27): note: see declaration of '<unnamed-symbol>'
<source>(135): error C2668: 'e3::f': ambiguous call to overloaded function
<source>(27): note: could be 'void e3::f<,>(void)'
<source>(24): note: or       'void e3::f<>(...)'
<source>(135): note: while trying to match the argument list '()'
<source>(135): error C2056: illegal expression
<source>(135): error C2607: static assertion failed

内容的提问来源于stack exchange,提问作者303

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 12:00:59