Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

01函数模板中的代码,gcc13.2 及以前的编译器运行存在 bug,已在 gcc14.1 被修复 #25

Closed
Side-Cloud opened this issue Mar 2, 2024 · 8 comments
Labels
bug 代码错误或解释不准确 compiler-bug 编译器存在BUG issue-luse 此 issue 有一定作用 issue-resolved 问题已解决

Comments

@Side-Cloud
Copy link

https://github.com/Mq-b/Modern-Cpp-templates-tutorial/blob/main/md/%E7%AC%AC%E4%B8%80%E9%83%A8%E5%88%86-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/01%E5%87%BD%E6%95%B0%E6%A8%A1%E6%9D%BF.md

template<typename T1,typename T2,typename RT = 
    decltype(true ? T1{} : T2{}) >
RT max(const T1& a, const T2& b) { // RT 是 std::string
    return a > b ? a : b;
}

在gcc不能运行
https://godbolt.org/z/685Y95vKW

T1,T2不一定是可{}构造的,应用declval,且去除引用返回
需改成如下

template<typename T1,typename T2,typename RT = 
    std::remove_reference_t< decltype(true ? 
    std::declval<T1>() : std::declval<T2>())> >
RT max(const T1& a, const T2& b) { // RT 是 std::string
    return a > b ? a : b;
}

https://godbolt.org/z/xd14YaPx6

@Mq-b
Copy link
Owner

Mq-b commented Mar 2, 2024

T1,T2不一定是可{}构造的,应用declval,且去除引用返回

我完全清楚的知道这个问题,这是我故意为之,我并不想在此时就开始教学 std::declval,过于抽象,前期视频使用简单的 T1{} 这样的写法,带入想象 int{} 更易教学。

你可以关注到教案的后续内容,在 SFINAE 中单独拿出一节来讲这个问题:

错误的原因很简单,decltype(T{} + T{}) 这个表达式中,同时要求了 T 类型支持默认构造(虽然这不是我们的本意),然而我们的 X2 类型没有默认构造,自然而然 T{} 不是合法表达式,代换失败。其实我们之前也有类似的写法,我们在本节进行纠正,使用 std::declval

@Mq-b Mq-b added the issue-luse 此 issue 有一定作用 label Mar 2, 2024
@Mq-b
Copy link
Owner

Mq-b commented Mar 2, 2024

在gcc不能运行

GCC 的报错是:

error: taking address of temporary array

先留着吧,把函数调用那里换成 ::max 还实在一点,,,

我感觉这是 GCC 的 bug,至少数组和 std::string 完全可以直接({})构造,这里涉及到了一些其他的问题可能。

@Mq-b Mq-b added bug 代码错误或解释不准确 review 还需要审阅 labels Mar 2, 2024
@Mq-b
Copy link
Owner

Mq-b commented Mar 2, 2024

@frederick-vs-ja

@Mq-b
Copy link
Owner

Mq-b commented Mar 2, 2024

#include <iostream>
#include <type_traits>

using namespace std::string_literals;

template<typename T1, typename T2, 
    typename RT = decltype(true ? T1{} : T2{})> 
RT max (T1 a, T2 b) {
    return b < a ? a : b;
}

int main(){
    auto ret = ::max("1", "2"s);
    std::cout << ret << '\n';
}

gcc 可以通过编译,我只是去除了 CVR,我感觉没有道理:https://godbolt.org/z/sWWePaf99

@rsp4jack
Copy link
Contributor

rsp4jack commented Mar 2, 2024

这个 labels 怎么乱七八糟的。

@frederick-vs-ja
Copy link
Contributor

是 gcc 的 bug ,已经修复了。

参考:

看起来大家都没有习惯检查 trunk 的表现……

@Mq-b
Copy link
Owner

Mq-b commented Mar 3, 2024

合理,和我猜想一样。

的确没有检查 trunk 的习惯。

ce4ce40

@Mq-b Mq-b added issue-resolved 问题已解决 and removed review 还需要审阅 labels Mar 3, 2024
@Mq-b Mq-b closed this as completed Mar 3, 2024
@Mq-b Mq-b added the compiler-bug 编译器存在BUG label Mar 29, 2024
@Mq-b
Copy link
Owner

Mq-b commented May 8, 2024

已发布 gcc14,解决了 gcc13.2 及以前的这块 bug,再次强调一下。
https://godbolt.org/z/MWKv8roo8

@Mq-b Mq-b changed the title 01函数模板中函数错误 01函数模板中的代码,gcc13.2 及以前的编译器运行存在 bug,已在 gcc14.1 被修复 May 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 代码错误或解释不准确 compiler-bug 编译器存在BUG issue-luse 此 issue 有一定作用 issue-resolved 问题已解决
Projects
None yet
Development

No branches or pull requests

4 participants