如何在不允许临时创建的情况下编写 const ref
How to write const ref without allowing temporary creation
我希望能够提供采用现有给定类型常量引用对象的函数。
即我想要按常量引用但不创建临时文件。 [编辑这句话以澄清它!]
我想不出有什么方法可以直接用 C++ 表达:
1 void fn(const T & t)
如果存在(非显式)T(S)
,将从 S
创建一个临时 T
。
2 void fn(T & t)
将只允许非 const t
作为参数(我需要它也适用于 const t
)。
3 void fn(T && t)
需要一个非常量 rvalue
.
4 void fn(const T && t)
需要 const rvalue
有什么方法可以做到这一点 - 通过引用接受任何参数,const,而不允许创建临时文件?
失败的想法:
在不提供其他两个的情况下提供 #2 和 #4,现在我们有一个明确的 fn
,它引用任何现有的 T
(但不会静默生成临时文件) ?
不,这也不够,因为我还需要能够绑定到 const T &
- 目标对象本身通过 const 引用传递给我们的调用者...
我想除了我可以控制 T
以确保它不提供隐式 T(S)
.
的情况外,我看不出有什么办法可以做到这一点
我是对的,还是我忽略了一些解决方案?
如果这是一个自由函数,那么您可以按照 nwp 的建议进行操作,并添加一个采用右值引用并将其删除的重载。
void fn(const SomeType& t)
{
// stuff to do with const lvalue
}
void fn(SomeType&&) = delete; // compiler error if you give me an rvalue
之所以可行,是因为右值引用优于对 const
的引用。因此,当重载解析开始并且您传递一个临时值时,编译器将 select void fn(const T&&)
作为最佳匹配。之后它会看到该函数被删除,它会发出编译错误
从评论来看,您的实际问题似乎与右值和左值无关,而只是防止隐式转换。您可以通过将函数更改为函数模板,然后使用 sfinae 约束模板来实现:
template <class T, std::enable_if_t<std::is_same<std::decay_t<T>, CString>::value, int> = 0>
void fn(const T&) {
}
这仅在使用某种 CString
调用时有效,隐式转换为 CString
的类型将无效。
实例:http://coliru.stacked-crooked.com/a/80602c39cdc4d35e
也就是说,更好的解决方案是简单地更改这些函数以接受 string_view
,它可以从各种字符串隐式构造,成本低廉。我不知道它是否处理 CString
或不,但你总是可以纠正你自己的。写起来相当简单class。 http://en.cppreference.com/w/cpp/string/basic_string_view
我希望能够提供采用现有给定类型常量引用对象的函数。
即我想要按常量引用但不创建临时文件。 [编辑这句话以澄清它!]
我想不出有什么方法可以直接用 C++ 表达:
1 void fn(const T & t)
如果存在(非显式)T(S)
,将从 S
创建一个临时 T
。
2 void fn(T & t)
将只允许非 const t
作为参数(我需要它也适用于 const t
)。
3 void fn(T && t)
需要一个非常量 rvalue
.
4 void fn(const T && t)
需要 const rvalue
有什么方法可以做到这一点 - 通过引用接受任何参数,const,而不允许创建临时文件?
失败的想法:
在不提供其他两个的情况下提供 #2 和 #4,现在我们有一个明确的 fn
,它引用任何现有的 T
(但不会静默生成临时文件) ?
不,这也不够,因为我还需要能够绑定到 const T &
- 目标对象本身通过 const 引用传递给我们的调用者...
我想除了我可以控制 T
以确保它不提供隐式 T(S)
.
我是对的,还是我忽略了一些解决方案?
如果这是一个自由函数,那么您可以按照 nwp 的建议进行操作,并添加一个采用右值引用并将其删除的重载。
void fn(const SomeType& t)
{
// stuff to do with const lvalue
}
void fn(SomeType&&) = delete; // compiler error if you give me an rvalue
之所以可行,是因为右值引用优于对 const
的引用。因此,当重载解析开始并且您传递一个临时值时,编译器将 select void fn(const T&&)
作为最佳匹配。之后它会看到该函数被删除,它会发出编译错误
从评论来看,您的实际问题似乎与右值和左值无关,而只是防止隐式转换。您可以通过将函数更改为函数模板,然后使用 sfinae 约束模板来实现:
template <class T, std::enable_if_t<std::is_same<std::decay_t<T>, CString>::value, int> = 0>
void fn(const T&) {
}
这仅在使用某种 CString
调用时有效,隐式转换为 CString
的类型将无效。
实例:http://coliru.stacked-crooked.com/a/80602c39cdc4d35e
也就是说,更好的解决方案是简单地更改这些函数以接受 string_view
,它可以从各种字符串隐式构造,成本低廉。我不知道它是否处理 CString
或不,但你总是可以纠正你自己的。写起来相当简单class。 http://en.cppreference.com/w/cpp/string/basic_string_view