是否可以参数化模板化成员函数的一致性
Is it possible to parameterize the constness of a templated member function?
模板使得函数签名的大部分内容都是可参数化的,除了函数名本身。但是是否也可以参数化成员函数的稳定性呢?
平凡的、极简的、非模板化的例子:
struct Foo {
Foo * self() { return this; }
Foo const * self() const { return this; }
};
vs 稻草人模板假设:
struct Foo {
template<typename T> T self() std::constness_of(T) { return this; }
};
但是是否也可以参数化成员函数的一致性呢?
不,你不能。在函数签名中不能访问this
所指向的隐式对象,因此不能以任何方式对其进行调度或对其进行模板。成员函数上的cv限定符必须拼写出来。
对于更复杂的成员函数,您可以让一个调用另一个(通常是非const
调用const
函数以避免UB)以避免一些代码重复。
或者你可以写一个非成员friend
:
struct Foo {
template <class T,
std::enable_if_t<std::is_base_of<Foo, std::decay_t<T>>::value>* = nullptr
>
friend T* self(T& x) { return &x; }
};
我们需要SFINAE来确保self()
不会被Wrapper<Foo>
等意外类型找到。请注意,这比您的原始代码要长得多,因此只有在具有复杂逻辑的上下文中才有意义。
肯定会很有趣,现在我们都通过非成员friend
来编写const
/非const
重载,我们仍然把它们当作成员来调用。
在另一个回答的评论中,你澄清了
”目标是随意自定义函数的一致性,而不需要在不需要的地方重复代码
下面是一种可能性,用模板化的static
成员函数表示const
和非const
版本的成员函数。
对于更一般的情况,需要转发参数。
两种替代方法是用非const
成员函数表示const
成员函数,反之亦然。但我记得,这涉及到一些丑陋的选角。或者一些丑陋,不确定(对不起,我现在坐在一个非常有限的互联网连接)。
#include <string>
//--------------------------------------- Machinery:
template< class Guide, class Result >
struct With_const_like_t_
{
using T = Result;
};
template< class Guide, class Result >
struct With_const_like_t_<Guide const, Result>
{
using T = Result const;
};
template< class Guide, class Result >
using With_const_like_ = typename With_const_like_t_<Guide, Result>::T;
//--------------------------------------- Example usage:
class Bork
{
private:
std::string s_ = "42";
template< class This_class >
static auto foo_impl( This_class& o )
-> With_const_like_<This_class, std::string>&
{ return o.s_; }
public:
auto foo()
-> decltype( foo_impl( *this ) )
{ return foo_impl( *this ); }
auto foo() const
-> decltype( foo_impl( *this ) )
{ return foo_impl( *this ); }
};
#include <iostream>
#include <typeinfo>
using namespace std;
auto main()
-> int
{
Bork v;
Bork const c;
v.foo() = "Hi there!";
#ifdef TEST
c.foo() = "This assignment to `const` won't compile.";
#endif
cout << v.foo() << endl;
}
不,但解决方法是直接的,也许更可读,意图是明确的:
struct Foo {
template<typename T>
std::enable_if_t<std::is_const<T>::value,T> self() const { return this; }
template<typename T>
std::enable_if_t<!std::is_const<T>::value,T> self() { return this; }
};
相关文章:
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 将公共但非静态的成员函数与ALGLIB集成
- 使用指向成员的指针将成员函数作为参数传递
- 将重载的成员函数传递给函数模板
- 我不小心调用了一个没有自己类对象的成员函数.但这是怎么回事呢
- 如何在C++中使用非静态成员函数作为回调函数
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 关联容器的下界复杂性:成员函数与非成员函数
- 在 C++ 中用派生类型重写成员函数
- 链表的泛型函数remove()与成员函数remove)
- 如何将lambda作为模板类的成员函数参数
- constexpr构造函数需要常量成员函数时出现问题
- 将自由函数绑定为类成员函数
- 区分非成员函数和头文件中的成员函数
- 如何从子成员函数修改父公共成员变量
- 保留对其他类的成员函数的引用
- 在运算符重载定义中使用成员函数(const错误)
- 内联如何影响模块接口中的成员函数
- 将成员函数指针作为参数传递给模板方法