通过 const 值返回并分配给非 const 变量编译
Returning by const value and assigning to a non const variable compiles
我不明白为什么允许以下代码使用 foo 的非 const 版本。我想禁止 const Array 变量提供非 const ArrayView。
#include <iostream>
struct ArrayView
{
ArrayView() = default;
ArrayView(const ArrayView&) = delete;
ArrayView(ArrayView&&) = delete;
void foo() {std::cout << "non const" << std::endl;}
void foo() const {std::cout << "const" << std::endl;}
};
struct Array
{
const ArrayView createView() const
{
return {};
}
};
int main()
{
const Array arr{};
auto view = arr.createView();
view.foo();
return 0;
}
输出:
non const
我在 windows 10.
上安装了 gcc 10.1.0
auto
的类型推导规则与模板参数推导相同; view
声明为非引用,createView
的 return 值的 const
部分被忽略。结果 view
的类型是 ArrayView
,而不是 const ArrayView
.
另一方面,如果您直接对 return 值调用 foo
,则会选择 const
版本。例如
arr.createView().foo();
作为解决方法,您可以将 view
显式声明为 const
,
const auto view = arr.createView();
或声明view
作为参考。
auto& view = arr.createView(); // the type of view is const ArrayView&
PS:我注意到您将 ArrayView
的 copy/move 构造函数标记为 delete
。由于 auto view = arr.createView();
中的 C++17,它们将因 mandatory copy elision 而被完全删除,它们是否可用在这里并不重要。
我不明白为什么允许以下代码使用 foo 的非 const 版本。我想禁止 const Array 变量提供非 const ArrayView。
#include <iostream>
struct ArrayView
{
ArrayView() = default;
ArrayView(const ArrayView&) = delete;
ArrayView(ArrayView&&) = delete;
void foo() {std::cout << "non const" << std::endl;}
void foo() const {std::cout << "const" << std::endl;}
};
struct Array
{
const ArrayView createView() const
{
return {};
}
};
int main()
{
const Array arr{};
auto view = arr.createView();
view.foo();
return 0;
}
输出:
non const
我在 windows 10.
上安装了 gcc 10.1.0auto
的类型推导规则与模板参数推导相同; view
声明为非引用,createView
的 return 值的 const
部分被忽略。结果 view
的类型是 ArrayView
,而不是 const ArrayView
.
另一方面,如果您直接对 return 值调用 foo
,则会选择 const
版本。例如
arr.createView().foo();
作为解决方法,您可以将 view
显式声明为 const
,
const auto view = arr.createView();
或声明view
作为参考。
auto& view = arr.createView(); // the type of view is const ArrayView&
PS:我注意到您将 ArrayView
的 copy/move 构造函数标记为 delete
。由于 auto view = arr.createView();
中的 C++17,它们将因 mandatory copy elision 而被完全删除,它们是否可用在这里并不重要。