我提出了一个宏,自动生成const/非const函数对。
class A
{
int x;
public:
MAYBE_CONST(
CV int &GetX() CV {return x;}
CV int &GetY() CV {return y;}
)
// Equivalent to:
// int &GetX() {return x;}
// int &GetY() {return y;}
// const int &GetX() const {return x;}
// const int &GetY() const {return y;}
};
有关实现,请参阅答案的末尾。
MAYBE_CONST的参数被复制。在第一份副本中,CV被替换为空白;在第二个副本中,它被替换为const。
CV在宏参数中出现的次数没有限制。
不过有一点小小的不便。如果CV出现在括号内,这对括号必须以CV_IN作为前缀:
// Doesn't work
MAYBE_CONST( CV int &foo(CV int &); )
// Works, expands to
// int &foo( int &);
// const int &foo(const int &);
MAYBE_CONST( CV int &foo CV_IN(CV int &); )
实现:
#define MAYBE_CONST(...) IMPL_CV_maybe_const( (IMPL_CV_null,__VA_ARGS__)() )
#define CV )(IMPL_CV_identity,
#define CV_IN(...) )(IMPL_CV_p_open,)(IMPL_CV_null,__VA_ARGS__)(IMPL_CV_p_close,)(IMPL_CV_null,
#define IMPL_CV_null(...)
#define IMPL_CV_identity(...) __VA_ARGS__
#define IMPL_CV_p_open(...) (
#define IMPL_CV_p_close(...) )
#define IMPL_CV_maybe_const(seq) IMPL_CV_a seq IMPL_CV_const_a seq
#define IMPL_CV_body(cv, m, ...) m(cv) __VA_ARGS__
#define IMPL_CV_a(...) __VA_OPT__(IMPL_CV_body(,__VA_ARGS__) IMPL_CV_b)
#define IMPL_CV_b(...) __VA_OPT__(IMPL_CV_body(,__VA_ARGS__) IMPL_CV_a)
#define IMPL_CV_const_a(...) __VA_OPT__(IMPL_CV_body(const,__VA_ARGS__) IMPL_CV_const_b)
#define IMPL_CV_const_b(...) __VA_OPT__(IMPL_CV_body(const,__VA_ARGS__) IMPL_CV_const_a)
pre - c++ 20实现,不支持CV_IN:
#define MAYBE_CONST(...) IMPL_MC( ((__VA_ARGS__)) )
#define CV ))((
#define IMPL_MC(seq) \
IMPL_MC_end(IMPL_MC_a seq) \
IMPL_MC_end(IMPL_MC_const_0 seq)
#define IMPL_MC_identity(...) __VA_ARGS__
#define IMPL_MC_end(...) IMPL_MC_end_(__VA_ARGS__)
#define IMPL_MC_end_(...) __VA_ARGS__##_end
#define IMPL_MC_a(elem) IMPL_MC_identity elem IMPL_MC_b
#define IMPL_MC_b(elem) IMPL_MC_identity elem IMPL_MC_a
#define IMPL_MC_a_end
#define IMPL_MC_b_end
#define IMPL_MC_const_0(elem) IMPL_MC_identity elem IMPL_MC_const_a
#define IMPL_MC_const_a(elem) const IMPL_MC_identity elem IMPL_MC_const_b
#define IMPL_MC_const_b(elem) const IMPL_MC_identity elem IMPL_MC_const_a
#define IMPL_MC_const_a_end
#define IMPL_MC_const_b_end