SFINAE 转换函数的奇怪警告[重复]

问题描述 投票:0回答:1

这是我的示例代码:

#include <type_traits>

template <bool B>
struct S {
    // #1
    // template <bool C = B, class = std::enable_if_t<!C>>
    // operator S<true>() const { return {}; }

    // #2
    // operator S<true>() const { return {}; }
};

int main() {
    S<true> b1;
    S<false> b2;
}

使用 g++ 编译时(https://godbolt.org/z/P46qE8EGG),无论启用选项 #1、选项 #2 还是两者都启用,我都不会收到警告。当我启用 #2 时,我希望收到一个警告,指出它是一个自转换函数,但也许 g++ 没有这样的警告。

真正的问题是用 clang 编译时。仅当我启用 #1 时,我才会收到以下警告:

错误:将“S”转换为自身的转换函数将永远不会被使用[-Werror,-Wclass-conversion]

启用 #2 不会触发此警告,禁用

b1
b2
的实例化也不会阻止此警告。到底是怎么回事?这是 clang 的错误吗?

编辑:我特别指的是为什么#1产生警告。其他信息旨在展示我尝试将问题缩小到更小的工作示例

c++ g++ clang
1个回答
0
投票

当我启用 #2 时,我希望收到一个警告,表明它是一个自转换函数,但也许 g++ 没有这样的警告。

正确,人们可以期待编译器警告(非标准最佳实践),但不能保证某个编译器会提供它们。

启用 #2 不会触发此警告,禁用 b1 或 b2 的实例化也不会阻止此警告。到底是怎么回事?这是 clang 的错误吗?

Clang 不警告

#2
是正确的,因为它可能会被调用,在删除定义的示例中更容易显示:

template <bool B>
struct S {  
    // #2
    operator S<true>() const = delete;
};

int main() {
    S<false> const b1;
    S<true> b2 = b1;  // error: call to a deleted function
}

为什么?由于隐式复制构造函数复制

S<true>  -> S<true>
S<false> -> S<false>

然而

S<false>
S<true>
并不是相同意义上的复制操作。

当“copy from”类为

S<false>
时,模板构造函数也存在,因此Clang确实不正确警告该函数永远不会被使用:

#include <type_traits>

template <bool B>
struct S {
    // #1
    template <bool C = B, class = std::enable_if_t<!C>>
    operator S<true>() const = delete;
};

int main() {
    S<false> const b1;
    S<true> b2 = b1;  // error: delete function
}
© www.soinside.com 2019 - 2024. All rights reserved.