gpt4 book ai didi

c++ - 为什么 g++ 从带有转换运算符和不可访问的函数调用运算符的类型中初始化 std::function<> 失败?

转载 作者:可可西里 更新时间:2023-11-01 18:35:30 24 4
gpt4 key购买 nike

此代码在 g++ 4.9 及更高版本(包括从 svn current 构建)中失败,但在没有警告的情况下使用 clang++ 和 Microsoft 编译器(来自 VS2015。)编译

#include <functional>

struct A {
void operator()() const {}
};
struct B {
void operator()() const {}
};
struct C : private A, private B
{
operator std::function<void()>() const { return nullptr; }
};

int main()
{
std::function<void()> f{C{}};
}

main()f 的构造失败,因为 operator() 在 struct C 中不明确.

为什么 g++ 认为这是不明确的? C 中的函数调用运算符是私有(private)继承的,不可访问。添加私有(private)的或显式删除的 void operator()() const 到结构 C 使代码按预期编译和使用转换运算符。为什么这些不可访问的运算符不会导致问题,而无法访问的继承运算符却会导致问题?

最佳答案

构造函数:template<class F> function(F f);

C++11:

f shall be Callable for argument types ArgTypes and return type R.

C++14:

Shall not participate in overload resolution unless f is Callable for argument types ArgTypes... and return type R.


在 C++11 中,此构造函数模板比​​涉及 std::function 的转换序列更匹配移动构造函数和您的用户定义的转换运算符。所以重载决议选择构造函数模板,然后编译失败,因为 f不是 Callable .

在 C++14 中,构造函数模板会发生替换失败,因为 f不是 Callable .所以构造函数模板不参与重载决策,剩下的最佳匹配是涉及std::function的转换序列移动构造函数和您的用户定义的转换运算符,因此使用它。


Clang 在 C++11 和 C++14 模式下编译您的测试用例。 GCC 在 C++11 和 C++14 模式下都拒绝您的测试用例。这是另一个在 GCC 中演示相同问题的测试用例:

#include <type_traits>

struct A {
void operator()() const {}
};
struct B {
void operator()() const {}
};
struct C : A, B {};

template <typename F, typename = std::result_of_t<F&()>>
void test(int) {}

template <typename F>
void test(double) {}

int main() {
test<C>(42);
}

test(int)不应参与重载决议,因为 std::result_of_t<F&()>应该是替换失败,所以 test(double)应该被调用。但是,此代码无法在 GCC 中编译。

这与在您的测试用例中看到的问题相同,因为这与在 std::function 的构造函数模板中用于实现 SFINAE 的机制相同。在 libstdc++ 中。

关于c++ - 为什么 g++ 从带有转换运算符和不可访问的函数调用运算符的类型中初始化 std::function<> 失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40706399/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com