gpt4 book ai didi

c++ - 模板函数无法将 'int' 转换为 nullptr_t

转载 作者:搜寻专家 更新时间:2023-10-30 23:53:20 26 4
gpt4 key购买 nike

长话短说:

为什么模板化函数不能访问非模板化函数可以访问的相同转换?

struct A {
A(std::nullptr_t) {}
};

template <typename T>
A makeA(T&& arg) {
return A(std::forward<T>(arg));
}

void foo() {
A a1(nullptr); //This works, of course
A a2(0); //This works
A a3 = makeA(0); //This does not
}

背景

我正在尝试编写一些模板化的包装器类以围绕现有类型使用,目的是作为直接替换,而无需重写使用现在包装的值的现有代码。

一个我无法理解的特殊情况如下:我们有一个可以从 std::nullptr_t(这里称为 A)构造的类,因此,有很多代码库中有人将零分配给实例的位置。

但是,尽管转发了构造函数,但不能为包装器分配零。我做了一个非常相似的例子,它在不使用实际包装类的情况下重现了这个问题——一个简单的模板化函数就足以说明这个问题。

我想继续允许能够分配零的语法 - 这不是我最喜欢的,但是为了让人们开始使用它们,尽量减少迁移到更新代码的摩擦通常是必要的.

我也不想添加一个接受除零以外的任何 int 的构造函数,因为这是非常荒谬的,以前是不允许的,它应该在编译时继续被捕获。

如果这样的事情不可能发生,找到一个解释会让我很满意,因为据我所知,这对我来说毫无意义。

此示例在 VC++(尽管 Intellisense 似乎可以接受...)、Clang 和 GCC 中具有相同的行为。理想情况下,一个解决方案也适用于所有 3 个(4 个带有智能感知)编译器。

更直接适用的例子如下:

struct A {
A(){}
A(std::nullptr_t) {}
};

template <typename T>
struct Wrapper {
A a;
Wrapper(const A& a):a (a) {}

template <typename T>
Wrapper(T&& t): a(std::forward<T>(t)){}

Wrapper(){}
};

void foo2() {
A a1;
a1 = 0; // This works

Wrapper<A> a2;
a2 = 0; //This does not
}

最佳答案

Why has the compiler decided to treat the zero as an int?

因为它是一个整数。

文字 0 是文字。文字开始做有趣的事情。字符串文字可以转换为const char*const char[N],其中N是字符串的长度+NUL终止符。文字 0 也可以做一些有趣的事情;它可用于用 NULL 指针常量初始化指针。并且它可用于初始化类型为nullptr_t 的对象。当然,它可以用来创建一个整数。

但是一旦它作为参数传递,它就不再是一个神奇的编译器构造。它成为具有具体类型的实际 C++ 对象。当谈到模板参数推导时,它得到最明显的类型:int

一旦它变成了一个 int,它就停止是一个文字 0 并且表现得与任何其他 int 完全一样。除非它在 ​​constexpr 上下文中使用(例如您的 int(0)),编译器可以在其中确定它确实是文字 0,因此可以接受它的神奇属性。函数参数永远不会是 constexpr,因此它们不能参与其中。

关于c++ - 模板函数无法将 'int' 转换为 nullptr_t,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41582864/

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