当前位置: 首页 > 知识库问答 >
问题:

在定义更有约束的版本之前和之后调用函数模板会产生奇怪的结果

轩辕华辉
2023-03-14

我的同事今天给我举了以下例子:

在gcc.godbolt.org上运行

#include <concepts>
#include <iostream>

template <typename T>
void foo(T)
{
    std::cout << "1\n";
}

template <typename T>
void bar(T value)
{
    foo(value);
}

void foo(std::same_as<int> auto)
{
    std::cout << "2\n";
}
    null

共有1个答案

习和通
2023-03-14

酷。每个编译器都是错误的。

中,对foo(value)的调用在作用域中仅可见未受约束的foo 。因此,当我们调用foo(value)时,唯一可能的候选者是(1)依赖于参数的查找所找到的(2)。由于在我们的示例中t=intint没有关联的名称空间,(2)是一个空集。因此,当bar(42)调用foo(42)时,foo是不受约束的模板,它应该打印1。

另一方面,在main中,foo(42)有两种不同的重载需要考虑:受约束的重载和无约束的重载。受约束的一个是可行的,而且比不受约束的一个更受约束,所以这是首选的。因此,在main()中,foo(42)应该调用受约束的foo(SAME_AS auto) ,它应该打印2。

总结一下:

>

  • clang错误,因为它显然缓存了foo 调用,这是不正确的--另一个foo重载不是专门化,而是重载,需要单独考虑。

    gcc的正确之处在于两个不同的foo调用调用两个不同的foo函数模板,但错误之处在于它破坏了两者,从而导致链接器错误。我是Itanium ABI#24。

    更有趣的是,如果将函数更改为constexpr int而不是void,则可以在编译时验证此行为...如:

    #include <concepts>
    #include <iostream>
    
    template <typename T>
    constexpr int foo(T)
    {
        return 1;
    }
    
    template <typename T>
    constexpr int bar(T value)
    {
        return foo(value);
    }
    
    constexpr int foo(std::same_as<int> auto)
    {
        return 2;
    }
    
    static_assert(bar(42) == 1);
    static_assert(foo(42) == 2);
    
    int main()
    {
        std::cout << bar(42) << '\n';
        std::cout << foo(42) << '\n';
    }
    

    然后clang进行编译(也就是说,它确实正确地从该点给出bar(42)==1foo(42)==2),但随后打印2两次。

    虽然gcc仍然在编译,但由于它对两个函数模板都进行了相同的修改,所以出现了相同的链接器错误。

  •  类似资料:
    • 我有一个结构,它有一个静态函数的多个重载,采用了一些< code >计数器 模板化的函数可用于查找该类中的特定重载: 在通常情况下,< code>count_fns 但是,添加调用< code>count_fns的内联静态变量会改变一些事情: Godbolt认为这种行为在编译器中是一致的(MSVC,gcc,clang): Demo 这是意料之中的,还是Constexr解释器的某种未定义行为? 以下

    • 本文向大家介绍PHP5.5和之前的版本empty函数的不同之处,包括了PHP5.5和之前的版本empty函数的不同之处的使用技巧和注意事项,需要的朋友参考一下 作为我最喜欢使用的函数之一,今天也终于发现这个函数的恶魔之处。洋洋洒洒写了以下代码,本地测试一切ok,到服务器上就SB了。 大致的意思就是,密码必须大于6位切不能只由数字组成。找遍服务器日志,发现如下错误: google了一下,大概是说,e

    • 问题内容: 我正在尝试使用SQL设置分页。我想要每页3个结果,这是我所做的: 我检查了很多次,这不是很复杂,但是我的结果并不是我所期望的: 第1页: 第2页 : 第3页: 第4页: 如您所见,第2、3和4页的结果相同…当我一次取4页时: 结果 : 也许我遗漏了一些东西或排序结果以及使用限制/偏移量不兼容,我不知道出了什么问题。 问题答案: 这里的问题是所有行的命中计数均为,因此使用时它们的位置是不

    • 在我的Android项目中,我必须将TextChangedListener(TextWatcher)添加到编辑文本视图中。它有三个部分: < Li > < code > ontext changed() < Li > < code > beforeTextChanged() < Li > < code > afterTextChanged() 这三个有什么区别?我必须在键侦听器上实现一个表搜索,对

    • 很明显,小的gc每隔5或6秒就会发生一次。 在2013-11-26T10:19:36.277之后,在2013-11-26T10:19:36.325有一个次要的gc只使用了20441K!!! 为什么会发生小的gc(行上方的blod)?谁知道啊? 更多详细信息: 内存总数16322984 KB jvm(热点1.6.0_26)的参数是: -xms7804m-xmx7804m-xmn2926m-xx:pe