constexpr parametrized function pointer - c++

I have the following third-party API:
using StatisticsFunc = double (*)(const std::vector<double> &)
libraryClass::ComputeStatistics(StatisticsFunc sf);
Which I'm using like this:
obj1->ComputeStatistics([](const auto& v) {return histogram("obj1", v);};
obj2->ComputeStatistics([](const auto& v) {return histogram("obj2", v);};
But all those lambdas are just repeated code. I'd rather have it like this:
obj1->ComputeStatistics(getHistogramLambda("obj1"));
So I need to define:
constexpr auto getHistogramLambda(const char* name) {
return [](const auto& v) {return histogram(name, v);};
}
But it won't work, because name is not captured. Neither will this work:
constexpr auto getHistogramLambda(const char* name) {
return [name](const auto& v) {return histogram(name, v);};
}
Because capturing lambda is not stateless anymore and cannot be cast to function pointer.
Ofc one can do it as a macro, but I want a modern C++ 17 solution.
Passing string as template argument seems an option as well:
https://stackoverflow.com/a/28209546/7432927 , but I'm curious if there's a constexpr way of doing it.

Sort of.
This:
obj1->ComputeStatistics(getHistogramLambda("obj1"));
Won't work for the reasons you point out - you need to capture state. And then, we can't write this:
obj1->ComputeStatistics(getHistogramLambda<"obj1">());
Because while we can have template parameters of type const char* we can't have them bind to string literals. You could do it this way:
template <const char* name>
constexpr auto getHistogramLambda() {
return [](const auto& v) {return histogram(name, v);};
}
const char p[] = "obj1";
obj1->ComputeStatistics(getHistogramLambda<p>());
Which is pretty awkward because you need to introduce the extra variable for each invocation. In C++20, we'll be able to write a class type that has as its template paramater a fixed string, which will allow getHistogramLambda<"obj1"> to work, just in a slightly different way.
Until then, the best way currently is probably to use a UDL to capture the individual characters as template parameters of some class type:
template <char... Cs>
constexpr auto getHistogramLambda(X<Cs...>) {
static constexpr char name[] = {Cs..., '\0'};
return [](const auto& v) { return histogram(name, v);};
}
obj->ComputeStatistic(getHistogramLambda("obj1"_udl));
The intent here is that "obj"_udl is an object of type X<'o', 'b', 'j', '1'> - and then we reconstruct the string within the body of the function template in a way that still does not require capture.
Is this worth it to avoid the duplication? Maybe.

Different answer, courtesy of Michael Park. We can encode the value we want in a type - not passing the string literal we want as a function argument or a template argument, but as an actual type - and that way we don't need to capture it:
#define CONSTANT(...) \
union { static constexpr auto value() { return __VA_ARGS__; } }
#define CONSTANT_VALUE(...) \
[] { using R = CONSTANT(__VA_ARGS__); return R{}; }()
template <typename X>
constexpr auto getHistogramLambda(X) {
return [](const auto& v) { return histogram(X::value(), v);};
}
obj->ComputeStatistic(getHistogramLambda(CONSTANT_VALUE("obj1")));
obj->ComputeStatistic(getHistogramLambda(CONSTANT_VALUE("obj2")));
Not sure this is better than the UDL approach in this particular case, but it's an interesting technique for sure.

Not sure to understand what do you exactly need but... what about declaring a global constexpr array of char const pointers
constexpr std::array<char const *, 3u> arrStr {{"obj0", "obj1", "obj2"}};
then receiving in getHistogramLambda() the index of the required string as template parameter?
template <std::size_t N>
constexpr auto getHistogramLambda () {
return [](const auto& v) {return histogram(arrStr.at(N), v);};
}
This way you can call ComputeStatistic() as follows
obj1->ComputeStatistics(getHistogramLambda<1u>());

Related

Prevent code duplication with both operator() and operator() const [duplicate]

Let's say I have the following class X where I want to return access to an internal member:
class Z
{
// details
};
class X
{
std::vector<Z> vecZ;
public:
Z& Z(size_t index)
{
// massive amounts of code for validating index
Z& ret = vecZ[index];
// even more code for determining that the Z instance
// at index is *exactly* the right sort of Z (a process
// which involves calculating leap years in which
// religious holidays fall on Tuesdays for
// the next thousand years or so)
return ret;
}
const Z& Z(size_t index) const
{
// identical to non-const X::Z(), except printed in
// a lighter shade of gray since
// we're running low on toner by this point
}
};
The two member functions X::Z() and X::Z() const have identical code inside the braces. This is duplicate code and can cause maintenance problems for long functions with complex logic.
Is there a way to avoid this code duplication?
For a detailed explanation, please see the heading "Avoid Duplication in const and Non-const Member Function," on p. 23, in Item 3 "Use const whenever possible," in Effective C++, 3d ed by Scott Meyers, ISBN-13: 9780321334879.
Here's Meyers' solution (simplified):
struct C {
const char & get() const {
return c;
}
char & get() {
return const_cast<char &>(static_cast<const C &>(*this).get());
}
char c;
};
The two casts and function call may be ugly, but it's correct in a non-const method as that implies the object was not const to begin with. (Meyers has a thorough discussion of this.)
C++17 has updated the best answer for this question:
T const & f() const {
return something_complicated();
}
T & f() {
return const_cast<T &>(std::as_const(*this).f());
}
This has the advantages that it:
Is obvious what is going on
Has minimal code overhead -- it fits in a single line
Is hard to get wrong (can only cast away volatile by accident, but volatile is a rare qualifier)
If you want to go the full deduction route then that can be accomplished by having a helper function
template<typename T>
constexpr T & as_mutable(T const & value) noexcept {
return const_cast<T &>(value);
}
template<typename T>
constexpr T * as_mutable(T const * value) noexcept {
return const_cast<T *>(value);
}
template<typename T>
constexpr T * as_mutable(T * value) noexcept {
return value;
}
template<typename T>
void as_mutable(T const &&) = delete;
Now you can't even mess up volatile, and the usage looks like
decltype(auto) f() const {
return something_complicated();
}
decltype(auto) f() {
return as_mutable(std::as_const(*this).f());
}
Yes, it is possible to avoid the code duplication. You need to use the const member function to have the logic and have the non-const member function call the const member function and re-cast the return value to a non-const reference (or pointer if the functions returns a pointer):
class X
{
std::vector<Z> vecZ;
public:
const Z& z(size_t index) const
{
// same really-really-really long access
// and checking code as in OP
// ...
return vecZ[index];
}
Z& z(size_t index)
{
// One line. One ugly, ugly line - but just one line!
return const_cast<Z&>( static_cast<const X&>(*this).z(index) );
}
#if 0 // A slightly less-ugly version
Z& Z(size_t index)
{
// Two lines -- one cast. This is slightly less ugly but takes an extra line.
const X& constMe = *this;
return const_cast<Z&>( constMe.z(index) );
}
#endif
};
NOTE: It is important that you do NOT put the logic in the non-const function and have the const-function call the non-const function -- it may result in undefined behavior. The reason is that a constant class instance gets cast as a non-constant instance. The non-const member function may accidentally modify the class, which the C++ standard states will result in undefined behavior.
I think Scott Meyers' solution can be improved in C++11 by using a tempate helper function. This makes the intent much more obvious and can be reused for many other getters.
template <typename T>
struct NonConst {typedef T type;};
template <typename T>
struct NonConst<T const> {typedef T type;}; //by value
template <typename T>
struct NonConst<T const&> {typedef T& type;}; //by reference
template <typename T>
struct NonConst<T const*> {typedef T* type;}; //by pointer
template <typename T>
struct NonConst<T const&&> {typedef T&& type;}; //by rvalue-reference
template<typename TConstReturn, class TObj, typename... TArgs>
typename NonConst<TConstReturn>::type likeConstVersion(
TObj const* obj,
TConstReturn (TObj::* memFun)(TArgs...) const,
TArgs&&... args) {
return const_cast<typename NonConst<TConstReturn>::type>(
(obj->*memFun)(std::forward<TArgs>(args)...));
}
This helper function can be used the following way.
struct T {
int arr[100];
int const& getElement(size_t i) const{
return arr[i];
}
int& getElement(size_t i) {
return likeConstVersion(this, &T::getElement, i);
}
};
The first argument is always the this-pointer. The second is the pointer to the member function to call. After that an arbitrary amount of additional arguments can be passed so that they can be forwarded to the function.
This needs C++11 because of the variadic templates.
Nice question and nice answers. I have another solution, that uses no casts:
class X {
private:
std::vector<Z> v;
template<typename InstanceType>
static auto get(InstanceType& instance, std::size_t i) -> decltype(instance.get(i)) {
// massive amounts of code for validating index
// the instance variable has to be used to access class members
return instance.v[i];
}
public:
const Z& get(std::size_t i) const {
return get(*this, i);
}
Z& get(std::size_t i) {
return get(*this, i);
}
};
However, it has the ugliness of requiring a static member and the need of using the instance variable inside it.
I did not consider all the possible (negative) implications of this solution. Please let me know if any.
A bit more verbose than Meyers, but I might do this:
class X {
private:
// This method MUST NOT be called except from boilerplate accessors.
Z &_getZ(size_t index) const {
return something;
}
// boilerplate accessors
public:
Z &getZ(size_t index) { return _getZ(index); }
const Z &getZ(size_t index) const { return _getZ(index); }
};
The private method has the undesirable property that it returns a non-const Z& for a const instance, which is why it's private. Private methods may break invariants of the external interface (in this case the desired invariant is "a const object cannot be modified via references obtained through it to objects it has-a").
Note that the comments are part of the pattern - _getZ's interface specifies that it is never valid to call it (aside from the accessors, obviously): there's no conceivable benefit to doing so anyway, because it's 1 more character to type and won't result in smaller or faster code. Calling the method is equivalent to calling one of the accessors with a const_cast, and you wouldn't want to do that either. If you're worried about making errors obvious (and that's a fair goal), then call it const_cast_getZ instead of _getZ.
By the way, I appreciate Meyers's solution. I have no philosophical objection to it. Personally, though, I prefer a tiny bit of controlled repetition, and a private method that must only be called in certain tightly-controlled circumstances, over a method that looks like line noise. Pick your poison and stick with it.
[Edit: Kevin has rightly pointed out that _getZ might want to call a further method (say generateZ) which is const-specialised in the same way getZ is. In this case, _getZ would see a const Z& and have to const_cast it before return. That's still safe, since the boilerplate accessor polices everything, but it's not outstandingly obvious that it's safe. Furthermore, if you do that and then later change generateZ to always return const, then you also need to change getZ to always return const, but the compiler won't tell you that you do.
That latter point about the compiler is also true of Meyers's recommended pattern, but the first point about a non-obvious const_cast isn't. So on balance I think that if _getZ turns out to need a const_cast for its return value, then this pattern loses a lot of its value over Meyers's. Since it also suffers disadvantages compared to Meyers's, I think I would switch to his in that situation. Refactoring from one to the other is easy -- it doesn't affect any other valid code in the class, since only invalid code and the boilerplate calls _getZ.]
C++23 has updated the best answer for this question thanks to deducing this:
struct s {
auto && f(this auto && self) {
// all the common code goes here
}
};
A single function template is callable as a normal member function and deduces the correct reference type for you. No casting to get wrong, no writing multiple functions for something that is conceptually one thing.
You could also solve this with templates. This solution is slightly ugly (but the ugliness is hidden in the .cpp file) but it does provide compiler checking of constness, and no code duplication.
.h file:
#include <vector>
class Z
{
// details
};
class X
{
std::vector<Z> vecZ;
public:
const std::vector<Z>& GetVector() const { return vecZ; }
std::vector<Z>& GetVector() { return vecZ; }
Z& GetZ( size_t index );
const Z& GetZ( size_t index ) const;
};
.cpp file:
#include "constnonconst.h"
template< class ParentPtr, class Child >
Child& GetZImpl( ParentPtr parent, size_t index )
{
// ... massive amounts of code ...
// Note you may only use methods of X here that are
// available in both const and non-const varieties.
Child& ret = parent->GetVector()[index];
// ... even more code ...
return ret;
}
Z& X::GetZ( size_t index )
{
return GetZImpl< X*, Z >( this, index );
}
const Z& X::GetZ( size_t index ) const
{
return GetZImpl< const X*, const Z >( this, index );
}
The main disadvantage I can see is that because all the complex implementation of the method is in a global function, you either need to get hold of the members of X using public methods like GetVector() above (of which there always need to be a const and non-const version) or you could make this function a friend. But I don't like friends.
[Edit: removed unneeded include of cstdio added during testing.]
For those (like me) who
use c++17
want to add the least amount of boilerplate/repetition and
don't mind using macros (while waiting for meta-classes...),
here is another take:
#include <utility>
#include <type_traits>
template <typename T> struct NonConst;
template <typename T> struct NonConst<T const&> {using type = T&;};
template <typename T> struct NonConst<T const*> {using type = T*;};
#define NON_CONST(func) \
template <typename... T> auto func(T&&... a) \
-> typename NonConst<decltype(func(std::forward<T>(a)...))>::type \
{ \
return const_cast<decltype(func(std::forward<T>(a)...))>( \
std::as_const(*this).func(std::forward<T>(a)...)); \
}
It is basically a mix of the answers from #Pait, #DavidStone and #sh1 (EDIT: and an improvement from #cdhowie). What it adds to the table is that you get away with only one extra line of code which simply names the function (but no argument or return type duplication):
class X
{
const Z& get(size_t index) const { ... }
NON_CONST(get)
};
Note: gcc fails to compile this prior to 8.1, clang-5 and upwards as well as MSVC-19 are happy (according to the compiler explorer).
If you don't like const casting, I use this C++17 version of the template static helper function suggested by another answer, with and optional SFINAE test.
#include <type_traits>
#define REQUIRES(...) class = std::enable_if_t<(__VA_ARGS__)>
#define REQUIRES_CV_OF(A,B) REQUIRES( std::is_same_v< std::remove_cv_t< A >, B > )
class Foobar {
private:
int something;
template<class FOOBAR, REQUIRES_CV_OF(FOOBAR, Foobar)>
static auto& _getSomething(FOOBAR& self, int index) {
// big, non-trivial chunk of code...
return self.something;
}
public:
auto& getSomething(int index) { return _getSomething(*this, index); }
auto& getSomething(int index) const { return _getSomething(*this, index); }
};
Full version: https://godbolt.org/z/mMK4r3
While most of answers here suggest to use a const_cast, CppCoreGuidelines have a section about that:
Instead, prefer to share implementations. Normally, you can just have the non-const function call the const function. However, when there is complex logic this can lead to the following pattern that still resorts to a const_cast:
class Foo {
public:
// not great, non-const calls const version but resorts to const_cast
Bar& get_bar()
{
return const_cast<Bar&>(static_cast<const Foo&>(*this).get_bar());
}
const Bar& get_bar() const
{
/* the complex logic around getting a const reference to my_bar */
}
private:
Bar my_bar;
};
Although this pattern is safe when applied correctly, because the
caller must have had a non-const object to begin with, it's not ideal
because the safety is hard to enforce automatically as a checker rule.
Instead, prefer to put the common code in a common helper function --
and make it a template so that it deduces const. This doesn't use any
const_cast at all:
class Foo {
public: // good
Bar& get_bar() { return get_bar_impl(*this); }
const Bar& get_bar() const { return get_bar_impl(*this); }
private:
Bar my_bar;
template<class T> // good, deduces whether T is const or non-const
static auto& get_bar_impl(T& t)
{ /* the complex logic around getting a possibly-const reference to my_bar */ }
};
Note: Don't do large non-dependent work inside a template, which leads to code bloat. For example, a further improvement would be if all or part of get_bar_impl can be non-dependent and factored out into a common non-template function, for a potentially big reduction in code size.
How about moving the logic into a private method, and only doing the "get the reference and return" stuff inside the getters? Actually, I would be fairly confused about the static and const casts inside a simple getter function, and I'd consider that ugly except for extremely rare circumstances!
I'd suggest a private helper static function template, like this:
class X
{
std::vector<Z> vecZ;
// ReturnType is explicitly 'Z&' or 'const Z&'
// ThisType is deduced to be 'X' or 'const X'
template <typename ReturnType, typename ThisType>
static ReturnType Z_impl(ThisType& self, size_t index)
{
// massive amounts of code for validating index
ReturnType ret = self.vecZ[index];
// even more code for determining, blah, blah...
return ret;
}
public:
Z& Z(size_t index)
{
return Z_impl<Z&>(*this, index);
}
const Z& Z(size_t index) const
{
return Z_impl<const Z&>(*this, index);
}
};
Is it cheating to use the preprocessor?
struct A {
#define GETTER_CORE_CODE \
/* line 1 of getter code */ \
/* line 2 of getter code */ \
/* .....etc............. */ \
/* line n of getter code */
// ^ NOTE: line continuation char '\' on all lines but the last
B& get() {
GETTER_CORE_CODE
}
const B& get() const {
GETTER_CORE_CODE
}
#undef GETTER_CORE_CODE
};
It's not as fancy as templates or casts, but it does make your intent ("these two functions are to be identical") pretty explicit.
It's surprising to me that there are so many different answers, yet almost all rely on heavy template magic. Templates are powerful, but sometimes macros beat them in conciseness. Maximum versatility is often achieved by combining both.
I wrote a macro FROM_CONST_OVERLOAD() which can be placed in the non-const function to invoke the const function.
Example usage:
class MyClass
{
private:
std::vector<std::string> data = {"str", "x"};
public:
// Works for references
const std::string& GetRef(std::size_t index) const
{
return data[index];
}
std::string& GetRef(std::size_t index)
{
return FROM_CONST_OVERLOAD( GetRef(index) );
}
// Works for pointers
const std::string* GetPtr(std::size_t index) const
{
return &data[index];
}
std::string* GetPtr(std::size_t index)
{
return FROM_CONST_OVERLOAD( GetPtr(index) );
}
};
Simple and reusable implementation:
template <typename T>
T& WithoutConst(const T& ref)
{
return const_cast<T&>(ref);
}
template <typename T>
T* WithoutConst(const T* ptr)
{
return const_cast<T*>(ptr);
}
template <typename T>
const T* WithConst(T* ptr)
{
return ptr;
}
#define FROM_CONST_OVERLOAD(FunctionCall) \
WithoutConst(WithConst(this)->FunctionCall)
Explanation:
As posted in many answers, the typical pattern to avoid code duplication in a non-const member function is this:
return const_cast<Result&>( static_cast<const MyClass*>(this)->Method(args) );
A lot of this boilerplate can be avoided using type inference. First, const_cast can be encapsulated in WithoutConst(), which infers the type of its argument and removes the const-qualifier. Second, a similar approach can be used in WithConst() to const-qualify the this pointer, which enables calling the const-overloaded method.
The rest is a simple macro that prefixes the call with the correctly qualified this-> and removes const from the result. Since the expression used in the macro is almost always a simple function call with 1:1 forwarded arguments, drawbacks of macros such as multiple evaluation do not kick in. The ellipsis and __VA_ARGS__ could also be used, but should not be needed because commas (as argument separators) occur within parentheses.
This approach has several benefits:
Minimal and natural syntax -- just wrap the call in FROM_CONST_OVERLOAD( )
No extra member function required
Compatible with C++98
Simple implementation, no template metaprogramming and zero dependencies
Extensible: other const relations can be added (like const_iterator, std::shared_ptr<const T>, etc.). For this, simply overload WithoutConst() for the corresponding types.
Limitations: this solution is optimized for scenarios where the non-const overload is doing exactly the same as the const overload, so that arguments can be forwarded 1:1. If your logic differs and you are not calling the const version via this->Method(args), you may consider other approaches.
I came up with a macro that generates pairs of const/non-const functions automatically.
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;}
};
See the end of the answer for the implementation.
The argument of MAYBE_CONST is duplicated. In the first copy, CV is replaced with nothing; and in the second copy it's replaced with const.
There's no limit on how many times CV can appear in the macro argument.
There's a slight inconvenience though. If CV appears inside of parentheses, this pair of parentheses must be prefixed with 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 &); )
Implementation:
#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 implementation that doesn't support 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
Typically, the member functions for which you need const and non-const versions are getters and setters. Most of the time they are one-liners so code duplication is not an issue.
I did this for a friend who rightfully justified the use of const_cast... not knowing about it I probably would have done something like this (not really elegant) :
#include <iostream>
class MyClass
{
public:
int getI()
{
std::cout << "non-const getter" << std::endl;
return privateGetI<MyClass, int>(*this);
}
const int getI() const
{
std::cout << "const getter" << std::endl;
return privateGetI<const MyClass, const int>(*this);
}
private:
template <class C, typename T>
static T privateGetI(C c)
{
//do my stuff
return c._i;
}
int _i;
};
int main()
{
const MyClass myConstClass = MyClass();
myConstClass.getI();
MyClass myNonConstClass;
myNonConstClass.getI();
return 0;
}
This DDJ article shows a way using template specialization that doesn't require you to use const_cast. For such a simple function it really isn't needed though.
boost::any_cast (at one point, it doesn't any more) uses a const_cast from the const version calling the non-const version to avoid duplication. You can't impose const semantics on the non-const version though so you have to be very careful with that.
In the end some code duplication is okay as long as the two snippets are directly on top of each other.
To add to the solution jwfearn and kevin provided, here's the corresponding solution when the function returns shared_ptr:
struct C {
shared_ptr<const char> get() const {
return c;
}
shared_ptr<char> get() {
return const_pointer_cast<char>(static_cast<const C &>(*this).get());
}
shared_ptr<char> c;
};
Didn't find what I was looking for, so I rolled a couple of my own...
This one is a little wordy, but has the advantage of handling many overloaded methods of the same name (and return type) all at once:
struct C {
int x[10];
int const* getp() const { return x; }
int const* getp(int i) const { return &x[i]; }
int const* getp(int* p) const { return &x[*p]; }
int const& getr() const { return x[0]; }
int const& getr(int i) const { return x[i]; }
int const& getr(int* p) const { return x[*p]; }
template<typename... Ts>
auto* getp(Ts... args) {
auto const* p = this;
return const_cast<int*>(p->getp(args...));
}
template<typename... Ts>
auto& getr(Ts... args) {
auto const* p = this;
return const_cast<int&>(p->getr(args...));
}
};
If you have only one const method per name, but still plenty of methods to duplicate, then you might prefer this:
template<typename T, typename... Ts>
auto* pwrap(T const* (C::*f)(Ts...) const, Ts... args) {
return const_cast<T*>((this->*f)(args...));
}
int* getp_i(int i) { return pwrap(&C::getp_i, i); }
int* getp_p(int* p) { return pwrap(&C::getp_p, p); }
Unfortunately this breaks down as soon as you start overloading the name (the function pointer argument's argument list seems to be unresolved at that point, so it can't find a match for the function argument). Although you can template your way out of that, too:
template<typename... Ts>
auto* getp(Ts... args) { return pwrap<int, Ts...>(&C::getp, args...); }
But reference arguments to the const method fail to match against the apparently by-value arguments to the template and it breaks. Not sure why.Here's why.

Transforming a string_view in-place

std::transform, as of C++20, is declared constexpr. I have a bunch of string utility functions that take std::string arguments, but a lot of the usage ends up just passing in small, short, character literal sequences at compile-time. I thought I would leverage this fact and declare versions that are constexpr and take std::string_views instead of creating temporary std::string variables just to throw them away...
ORIGINAL STD::STRING VERSION:
[[nodiscard]] std::string ToUpperCase(std::string string) noexcept {
std::transform(string.begin(), string.end(), string.begin(), [](unsigned char c) -> unsigned char { return std::toupper(c, std::locale("")); });
return string;
}
NEW STD::STRING_VIEW VERSION:
[[nodiscard]] constexpr std::string_view ToUpperCase(std::string_view stringview) noexcept {
std::transform(stringview.begin(), stringview.end(), stringview.begin(), [](unsigned char c) -> unsigned char { return std::toupper(c, std::locale("")); });
return stringview;
}
But MSVC complains:
error C3892: '_UDest': you cannot assign to a variable that is const
Is there a way to call std::transform with a std::string_view and put it back into the std::string_view or am I going to have to create a local string and return that, thereby defeating the purpose of using std::string_view in the first place?
[[nodiscard]] constexpr std::string ToUpperCase(std::string_view stringview) noexcept {
std::string copy{stringview};
std::transform(stringview.begin(), stringview.end(), copy.begin(), [](unsigned char c) -> unsigned char { return std::toupper(c, std::locale("")); });
return copy;
}
You can't in-place transform a std::string_view - what if it has been constructed from char const*?
a lot of the usage ends up just passing in small, short, character literal sequences at compile-time.
...but you can lift string literals to the type level
namespace impl {
template<std::size_t n> struct Str {
std::array<char, n> raw{};
constexpr Str(char const (&src)[n + 1]) { std::copy_n(src, n, raw.begin()); }
};
template<std::size_t n> Str(char const (&)[n]) -> Str<n - 1>;
}
template<char... cs> struct Str { static char constexpr value[]{cs..., '\0'}; };
template<impl::Str s>
auto constexpr str_v = []<std::size_t... is>(std::index_sequence<is...>) {
return Str<s.raw[is]...>{};
}(std::make_index_sequence<s.raw.size()>{});
...and add a special case. In general, this hack can be avoided with range/tuple polymorphic algorithms.
[[nodiscard]] constexpr auto ToUpperCase(auto str) {
for (auto&& c: str) c = ConstexprToUpper(c); // std::toupper doesn't seem constexpr
return str;
}
template<char... cs> [[nodiscard]] constexpr auto ToUpperCase(Str<cs...>) {
return Str<ConstexprToUpper(cs)...>{};
}
So, to use that transformation optimized for character literal sequences, now write ToUpperCase(str_v<"abc">) instead of ToUpperCase("abc"sv). If you always want string_view as output, return std::string_view{Str<ConstexprToUpper(cs)...>::value} in that overload.
As said in one comment, span is a better vocabulary type for this because individual elements can be modified.
Also I wouldn't make it nodiscard, because it can be useful even without assigning the result:
#include<algorithm>
#include<cassert>
#include<cctype>
#include<locale>
#include<string_view>
#include<span>
constexpr std::span<char> ToUpperCase(std::span<char> stringview) noexcept {
std::transform(stringview.begin(), stringview.end(), stringview.begin(), [](unsigned char c) -> unsigned char { return std::toupper(c); });
return stringview;
}
int main() {
std::string a = "compiler";
std::string b = ToUpperCase(a);
assert( a == "COMPILER");
assert( b == "COMPILER");
}
https://godbolt.org/z/Toz8Y9bj9
Somewhat departing from your original aim...
I think this is more elegant, although subject to bloating and ugly compilation errors.
It has the same effect in the cases provided.
Also I don't like the design of span (or string_view for that matter)
(Exercise: add Concepts)
template<class StringRange>
constexpr StringRange&& ToUpperCase(StringRange&& stringview) noexcept {
std::transform(stringview.begin(), stringview.end(), stringview.begin(), [](unsigned char c) -> unsigned char { return std::toupper(c); });
return std::forward<StringRange>(stringview);
}
https://godbolt.org/z/e9aWKMerE
I find myself using this idiom quite a bit lately.

How to write function with the matching const modifier on argument and return types?

I want to write a function that extracts a pointer field from a struct. The requirement is that if I pass the struct as a const argument, the returned type should be const. If not, the returned type should not be const.
For instance,
struct S {
char *p;
};
// approach 1: two overload functions with duplicate body
auto extract(S &input) -> int * {
return reinterpret_cast<int *>(input.p + 12);
}
auto extract(const S &input) -> const int * {
return reinterpret_cast<const int *>(input.p + 12);
}
// approach 2: macro
#define macro_extract(input) (reinterpret_cast<int *>(input.p + 12))
Is there any trick in template or latest C++ standard that can write a strongly typed function without duplicating the body?
EDIT:
Changed the example a bit to reflect more accurately of the real problem.
Here's a solution with a single function template:
template<typename T,
typename = std::enable_if_t<
std::is_same_v<
std::remove_cv_t<
std::remove_reference_t<T>>, S>>>
auto extract(T&& input)
-> std::conditional_t<
std::is_const_v<
std::remove_reference_t<T>>, int const *, int *>
{
return input.p;
}
Here's a demo.
I think it goes without saying that you'd be better off with an overload set. If the function body is large, you can still call the non-const version from the const overload, and add the const there.
if constexpr and auto as return type solution:
#include <type_traits>
struct S {
int *p;
};
template<typename T>
auto extract(T &&input) {
static_assert(std::is_same_v<std::decay_t<decltype(input)>,S>, , "Only struct S is supported");
if constexpr(!std::is_const_v<std::remove_reference_t<decltype(input)>>) {
return input.p;
} else {
return const_cast<const int*>(input.p);
}
}
int main () {
S i;
using t = decltype(extract(i));
static_assert(std::is_same_v<t,int*>);
S const i_c{0};
using t_c = decltype(extract(i_c));
static_assert(std::is_same_v<t_c,const int*>);
return 0;
}
PLZ look at the ISO proposal:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4388.html
And the std::experimental::propagate_const spec:
https://en.cppreference.com/w/cpp/experimental/propagate_const
Or one can implement his own version of propagate_const.
have fun,
FM
SFINAE should be able to do this. The approximate format is:
template<class T,
class allow=std::enable_if_t<std::is_base_of_v<S, T>>>
auto extract(T&& input) -> decltype(input.p) {
return input.p;
}
Basically using universal forwarding references to make it work for anything: S, S&, const S&, S&&, volatile S&, etc.

Need to Total Fields From a Container of structs

This is more of a code clenliness question, cause I already have an example here. I'm doing this a ton in code and the creation of all these lambdas (some of which are the same) has begun to irk me.
So given the struct:
struct foo {
int b() const { return _b; }
int a() const { return _a; }
int r() const { return _r; }
const int _b;
const int _a;
const int _r;
};
I have a container of pointers to them, let's say vector<foo*> foos, now I want to go through the container and get the sum of one of the fields.
As an example if I wanted the field _r, then my current approach is to do this:
accumulate(cbegin(foos), cend(foos), 0, [](const auto init, const auto i) { return init + i->r(); } )
I'm writing this line everywhere. Can any improvement be made upon this? I'd really like to write something like this:
x(cbegin(foos), cend(foos), mem_fn(&foo::r));
I don't think the standard provides anything like that. I could obviously write it, but then it would require the reader to go figure out my suspect code instead of just knowing what accumulate does.
Instead of writing a custom accumulate, I suggest writing a custom functor generator, that returns a functor that can be used as an argument to std::accumulate.
template<class Fun>
auto mem_accumulator(Fun member_function) {
return [=](auto init, auto i) {
return init + (i->*member_function)();
};
}
then
accumulate(cbegin(foos), cend(foos), 0, mem_accumulator(&foo::r));
A few variations:
For containers of objects:
template<class MemFun>
auto mem_accumulator(MemFun member_function) {
return [=](auto init, auto i) {
return init + (i.*member_function)();
};
}
Use data member pointers instead of functions:
template<class T>
auto mem_accumulator(T member_ptr) {
return [=](auto init, auto i) {
return init + i->*member_ptr;
};
}
// ...
accumulator(&foo::_r)
Support functors, rather than member function pointers:
template<class Fun>
auto accumulator(Fun fun) {
return [=](auto init, auto i) {
return init + fun(i);
};
}
// ...
accumulator(std::mem_fun(&foo::r))
Some (all?) of these variations could perhaps be combined to be selected automatically with some SFINAE magic, but that will increase complexity.
There is actually a really elegant way to solve this using Variable Templates which were introduced in c++14. We can templatize a lambda variable using the method pointer as the template argument:
template <int (foo::*T)()>
auto func = [](const auto init, const auto i){ return init + (i->*T)(); };
Passing the func appropriate specialization of func as the last argument to accumulate will have the same effect as writing out the lambda in place:
accumulate(cbegin(foos), cend(foos), 0, func<&foo::r>)
Live Example
Another alternative based off the same templatization premise, which does not require c++14, is the templatized function suggested by StoryTeller:
template <int (foo::*T)()>
int func(const int init, const foo* i) { return init + (i->*T)(); }
Which could also be used by simply passing the method pointer:
accumulate(cbegin(foos), cend(foos), 0, &func<&foo::r>)
Live Example
The specificity required by both these examples has been removed in c++17 where we can use auto for template parameter types: http://en.cppreference.com/w/cpp/language/auto This will allow us to declare func so it can be used by any class, not just foo:
template <auto T>
auto func(const auto init, const auto i) { return init + (i->*T)(); }

How do I remove code duplication between similar const and non-const member functions?

Let's say I have the following class X where I want to return access to an internal member:
class Z
{
// details
};
class X
{
std::vector<Z> vecZ;
public:
Z& Z(size_t index)
{
// massive amounts of code for validating index
Z& ret = vecZ[index];
// even more code for determining that the Z instance
// at index is *exactly* the right sort of Z (a process
// which involves calculating leap years in which
// religious holidays fall on Tuesdays for
// the next thousand years or so)
return ret;
}
const Z& Z(size_t index) const
{
// identical to non-const X::Z(), except printed in
// a lighter shade of gray since
// we're running low on toner by this point
}
};
The two member functions X::Z() and X::Z() const have identical code inside the braces. This is duplicate code and can cause maintenance problems for long functions with complex logic.
Is there a way to avoid this code duplication?
For a detailed explanation, please see the heading "Avoid Duplication in const and Non-const Member Function," on p. 23, in Item 3 "Use const whenever possible," in Effective C++, 3d ed by Scott Meyers, ISBN-13: 9780321334879.
Here's Meyers' solution (simplified):
struct C {
const char & get() const {
return c;
}
char & get() {
return const_cast<char &>(static_cast<const C &>(*this).get());
}
char c;
};
The two casts and function call may be ugly, but it's correct in a non-const method as that implies the object was not const to begin with. (Meyers has a thorough discussion of this.)
C++17 has updated the best answer for this question:
T const & f() const {
return something_complicated();
}
T & f() {
return const_cast<T &>(std::as_const(*this).f());
}
This has the advantages that it:
Is obvious what is going on
Has minimal code overhead -- it fits in a single line
Is hard to get wrong (can only cast away volatile by accident, but volatile is a rare qualifier)
If you want to go the full deduction route then that can be accomplished by having a helper function
template<typename T>
constexpr T & as_mutable(T const & value) noexcept {
return const_cast<T &>(value);
}
template<typename T>
constexpr T * as_mutable(T const * value) noexcept {
return const_cast<T *>(value);
}
template<typename T>
constexpr T * as_mutable(T * value) noexcept {
return value;
}
template<typename T>
void as_mutable(T const &&) = delete;
Now you can't even mess up volatile, and the usage looks like
decltype(auto) f() const {
return something_complicated();
}
decltype(auto) f() {
return as_mutable(std::as_const(*this).f());
}
Yes, it is possible to avoid the code duplication. You need to use the const member function to have the logic and have the non-const member function call the const member function and re-cast the return value to a non-const reference (or pointer if the functions returns a pointer):
class X
{
std::vector<Z> vecZ;
public:
const Z& z(size_t index) const
{
// same really-really-really long access
// and checking code as in OP
// ...
return vecZ[index];
}
Z& z(size_t index)
{
// One line. One ugly, ugly line - but just one line!
return const_cast<Z&>( static_cast<const X&>(*this).z(index) );
}
#if 0 // A slightly less-ugly version
Z& Z(size_t index)
{
// Two lines -- one cast. This is slightly less ugly but takes an extra line.
const X& constMe = *this;
return const_cast<Z&>( constMe.z(index) );
}
#endif
};
NOTE: It is important that you do NOT put the logic in the non-const function and have the const-function call the non-const function -- it may result in undefined behavior. The reason is that a constant class instance gets cast as a non-constant instance. The non-const member function may accidentally modify the class, which the C++ standard states will result in undefined behavior.
I think Scott Meyers' solution can be improved in C++11 by using a tempate helper function. This makes the intent much more obvious and can be reused for many other getters.
template <typename T>
struct NonConst {typedef T type;};
template <typename T>
struct NonConst<T const> {typedef T type;}; //by value
template <typename T>
struct NonConst<T const&> {typedef T& type;}; //by reference
template <typename T>
struct NonConst<T const*> {typedef T* type;}; //by pointer
template <typename T>
struct NonConst<T const&&> {typedef T&& type;}; //by rvalue-reference
template<typename TConstReturn, class TObj, typename... TArgs>
typename NonConst<TConstReturn>::type likeConstVersion(
TObj const* obj,
TConstReturn (TObj::* memFun)(TArgs...) const,
TArgs&&... args) {
return const_cast<typename NonConst<TConstReturn>::type>(
(obj->*memFun)(std::forward<TArgs>(args)...));
}
This helper function can be used the following way.
struct T {
int arr[100];
int const& getElement(size_t i) const{
return arr[i];
}
int& getElement(size_t i) {
return likeConstVersion(this, &T::getElement, i);
}
};
The first argument is always the this-pointer. The second is the pointer to the member function to call. After that an arbitrary amount of additional arguments can be passed so that they can be forwarded to the function.
This needs C++11 because of the variadic templates.
Nice question and nice answers. I have another solution, that uses no casts:
class X {
private:
std::vector<Z> v;
template<typename InstanceType>
static auto get(InstanceType& instance, std::size_t i) -> decltype(instance.get(i)) {
// massive amounts of code for validating index
// the instance variable has to be used to access class members
return instance.v[i];
}
public:
const Z& get(std::size_t i) const {
return get(*this, i);
}
Z& get(std::size_t i) {
return get(*this, i);
}
};
However, it has the ugliness of requiring a static member and the need of using the instance variable inside it.
I did not consider all the possible (negative) implications of this solution. Please let me know if any.
A bit more verbose than Meyers, but I might do this:
class X {
private:
// This method MUST NOT be called except from boilerplate accessors.
Z &_getZ(size_t index) const {
return something;
}
// boilerplate accessors
public:
Z &getZ(size_t index) { return _getZ(index); }
const Z &getZ(size_t index) const { return _getZ(index); }
};
The private method has the undesirable property that it returns a non-const Z& for a const instance, which is why it's private. Private methods may break invariants of the external interface (in this case the desired invariant is "a const object cannot be modified via references obtained through it to objects it has-a").
Note that the comments are part of the pattern - _getZ's interface specifies that it is never valid to call it (aside from the accessors, obviously): there's no conceivable benefit to doing so anyway, because it's 1 more character to type and won't result in smaller or faster code. Calling the method is equivalent to calling one of the accessors with a const_cast, and you wouldn't want to do that either. If you're worried about making errors obvious (and that's a fair goal), then call it const_cast_getZ instead of _getZ.
By the way, I appreciate Meyers's solution. I have no philosophical objection to it. Personally, though, I prefer a tiny bit of controlled repetition, and a private method that must only be called in certain tightly-controlled circumstances, over a method that looks like line noise. Pick your poison and stick with it.
[Edit: Kevin has rightly pointed out that _getZ might want to call a further method (say generateZ) which is const-specialised in the same way getZ is. In this case, _getZ would see a const Z& and have to const_cast it before return. That's still safe, since the boilerplate accessor polices everything, but it's not outstandingly obvious that it's safe. Furthermore, if you do that and then later change generateZ to always return const, then you also need to change getZ to always return const, but the compiler won't tell you that you do.
That latter point about the compiler is also true of Meyers's recommended pattern, but the first point about a non-obvious const_cast isn't. So on balance I think that if _getZ turns out to need a const_cast for its return value, then this pattern loses a lot of its value over Meyers's. Since it also suffers disadvantages compared to Meyers's, I think I would switch to his in that situation. Refactoring from one to the other is easy -- it doesn't affect any other valid code in the class, since only invalid code and the boilerplate calls _getZ.]
C++23 has updated the best answer for this question thanks to deducing this:
struct s {
auto && f(this auto && self) {
// all the common code goes here
}
};
A single function template is callable as a normal member function and deduces the correct reference type for you. No casting to get wrong, no writing multiple functions for something that is conceptually one thing.
You could also solve this with templates. This solution is slightly ugly (but the ugliness is hidden in the .cpp file) but it does provide compiler checking of constness, and no code duplication.
.h file:
#include <vector>
class Z
{
// details
};
class X
{
std::vector<Z> vecZ;
public:
const std::vector<Z>& GetVector() const { return vecZ; }
std::vector<Z>& GetVector() { return vecZ; }
Z& GetZ( size_t index );
const Z& GetZ( size_t index ) const;
};
.cpp file:
#include "constnonconst.h"
template< class ParentPtr, class Child >
Child& GetZImpl( ParentPtr parent, size_t index )
{
// ... massive amounts of code ...
// Note you may only use methods of X here that are
// available in both const and non-const varieties.
Child& ret = parent->GetVector()[index];
// ... even more code ...
return ret;
}
Z& X::GetZ( size_t index )
{
return GetZImpl< X*, Z >( this, index );
}
const Z& X::GetZ( size_t index ) const
{
return GetZImpl< const X*, const Z >( this, index );
}
The main disadvantage I can see is that because all the complex implementation of the method is in a global function, you either need to get hold of the members of X using public methods like GetVector() above (of which there always need to be a const and non-const version) or you could make this function a friend. But I don't like friends.
[Edit: removed unneeded include of cstdio added during testing.]
For those (like me) who
use c++17
want to add the least amount of boilerplate/repetition and
don't mind using macros (while waiting for meta-classes...),
here is another take:
#include <utility>
#include <type_traits>
template <typename T> struct NonConst;
template <typename T> struct NonConst<T const&> {using type = T&;};
template <typename T> struct NonConst<T const*> {using type = T*;};
#define NON_CONST(func) \
template <typename... T> auto func(T&&... a) \
-> typename NonConst<decltype(func(std::forward<T>(a)...))>::type \
{ \
return const_cast<decltype(func(std::forward<T>(a)...))>( \
std::as_const(*this).func(std::forward<T>(a)...)); \
}
It is basically a mix of the answers from #Pait, #DavidStone and #sh1 (EDIT: and an improvement from #cdhowie). What it adds to the table is that you get away with only one extra line of code which simply names the function (but no argument or return type duplication):
class X
{
const Z& get(size_t index) const { ... }
NON_CONST(get)
};
Note: gcc fails to compile this prior to 8.1, clang-5 and upwards as well as MSVC-19 are happy (according to the compiler explorer).
If you don't like const casting, I use this C++17 version of the template static helper function suggested by another answer, with and optional SFINAE test.
#include <type_traits>
#define REQUIRES(...) class = std::enable_if_t<(__VA_ARGS__)>
#define REQUIRES_CV_OF(A,B) REQUIRES( std::is_same_v< std::remove_cv_t< A >, B > )
class Foobar {
private:
int something;
template<class FOOBAR, REQUIRES_CV_OF(FOOBAR, Foobar)>
static auto& _getSomething(FOOBAR& self, int index) {
// big, non-trivial chunk of code...
return self.something;
}
public:
auto& getSomething(int index) { return _getSomething(*this, index); }
auto& getSomething(int index) const { return _getSomething(*this, index); }
};
Full version: https://godbolt.org/z/mMK4r3
While most of answers here suggest to use a const_cast, CppCoreGuidelines have a section about that:
Instead, prefer to share implementations. Normally, you can just have the non-const function call the const function. However, when there is complex logic this can lead to the following pattern that still resorts to a const_cast:
class Foo {
public:
// not great, non-const calls const version but resorts to const_cast
Bar& get_bar()
{
return const_cast<Bar&>(static_cast<const Foo&>(*this).get_bar());
}
const Bar& get_bar() const
{
/* the complex logic around getting a const reference to my_bar */
}
private:
Bar my_bar;
};
Although this pattern is safe when applied correctly, because the
caller must have had a non-const object to begin with, it's not ideal
because the safety is hard to enforce automatically as a checker rule.
Instead, prefer to put the common code in a common helper function --
and make it a template so that it deduces const. This doesn't use any
const_cast at all:
class Foo {
public: // good
Bar& get_bar() { return get_bar_impl(*this); }
const Bar& get_bar() const { return get_bar_impl(*this); }
private:
Bar my_bar;
template<class T> // good, deduces whether T is const or non-const
static auto& get_bar_impl(T& t)
{ /* the complex logic around getting a possibly-const reference to my_bar */ }
};
Note: Don't do large non-dependent work inside a template, which leads to code bloat. For example, a further improvement would be if all or part of get_bar_impl can be non-dependent and factored out into a common non-template function, for a potentially big reduction in code size.
How about moving the logic into a private method, and only doing the "get the reference and return" stuff inside the getters? Actually, I would be fairly confused about the static and const casts inside a simple getter function, and I'd consider that ugly except for extremely rare circumstances!
I'd suggest a private helper static function template, like this:
class X
{
std::vector<Z> vecZ;
// ReturnType is explicitly 'Z&' or 'const Z&'
// ThisType is deduced to be 'X' or 'const X'
template <typename ReturnType, typename ThisType>
static ReturnType Z_impl(ThisType& self, size_t index)
{
// massive amounts of code for validating index
ReturnType ret = self.vecZ[index];
// even more code for determining, blah, blah...
return ret;
}
public:
Z& Z(size_t index)
{
return Z_impl<Z&>(*this, index);
}
const Z& Z(size_t index) const
{
return Z_impl<const Z&>(*this, index);
}
};
Is it cheating to use the preprocessor?
struct A {
#define GETTER_CORE_CODE \
/* line 1 of getter code */ \
/* line 2 of getter code */ \
/* .....etc............. */ \
/* line n of getter code */
// ^ NOTE: line continuation char '\' on all lines but the last
B& get() {
GETTER_CORE_CODE
}
const B& get() const {
GETTER_CORE_CODE
}
#undef GETTER_CORE_CODE
};
It's not as fancy as templates or casts, but it does make your intent ("these two functions are to be identical") pretty explicit.
It's surprising to me that there are so many different answers, yet almost all rely on heavy template magic. Templates are powerful, but sometimes macros beat them in conciseness. Maximum versatility is often achieved by combining both.
I wrote a macro FROM_CONST_OVERLOAD() which can be placed in the non-const function to invoke the const function.
Example usage:
class MyClass
{
private:
std::vector<std::string> data = {"str", "x"};
public:
// Works for references
const std::string& GetRef(std::size_t index) const
{
return data[index];
}
std::string& GetRef(std::size_t index)
{
return FROM_CONST_OVERLOAD( GetRef(index) );
}
// Works for pointers
const std::string* GetPtr(std::size_t index) const
{
return &data[index];
}
std::string* GetPtr(std::size_t index)
{
return FROM_CONST_OVERLOAD( GetPtr(index) );
}
};
Simple and reusable implementation:
template <typename T>
T& WithoutConst(const T& ref)
{
return const_cast<T&>(ref);
}
template <typename T>
T* WithoutConst(const T* ptr)
{
return const_cast<T*>(ptr);
}
template <typename T>
const T* WithConst(T* ptr)
{
return ptr;
}
#define FROM_CONST_OVERLOAD(FunctionCall) \
WithoutConst(WithConst(this)->FunctionCall)
Explanation:
As posted in many answers, the typical pattern to avoid code duplication in a non-const member function is this:
return const_cast<Result&>( static_cast<const MyClass*>(this)->Method(args) );
A lot of this boilerplate can be avoided using type inference. First, const_cast can be encapsulated in WithoutConst(), which infers the type of its argument and removes the const-qualifier. Second, a similar approach can be used in WithConst() to const-qualify the this pointer, which enables calling the const-overloaded method.
The rest is a simple macro that prefixes the call with the correctly qualified this-> and removes const from the result. Since the expression used in the macro is almost always a simple function call with 1:1 forwarded arguments, drawbacks of macros such as multiple evaluation do not kick in. The ellipsis and __VA_ARGS__ could also be used, but should not be needed because commas (as argument separators) occur within parentheses.
This approach has several benefits:
Minimal and natural syntax -- just wrap the call in FROM_CONST_OVERLOAD( )
No extra member function required
Compatible with C++98
Simple implementation, no template metaprogramming and zero dependencies
Extensible: other const relations can be added (like const_iterator, std::shared_ptr<const T>, etc.). For this, simply overload WithoutConst() for the corresponding types.
Limitations: this solution is optimized for scenarios where the non-const overload is doing exactly the same as the const overload, so that arguments can be forwarded 1:1. If your logic differs and you are not calling the const version via this->Method(args), you may consider other approaches.
I came up with a macro that generates pairs of const/non-const functions automatically.
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;}
};
See the end of the answer for the implementation.
The argument of MAYBE_CONST is duplicated. In the first copy, CV is replaced with nothing; and in the second copy it's replaced with const.
There's no limit on how many times CV can appear in the macro argument.
There's a slight inconvenience though. If CV appears inside of parentheses, this pair of parentheses must be prefixed with 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 &); )
Implementation:
#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 implementation that doesn't support 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
Typically, the member functions for which you need const and non-const versions are getters and setters. Most of the time they are one-liners so code duplication is not an issue.
I did this for a friend who rightfully justified the use of const_cast... not knowing about it I probably would have done something like this (not really elegant) :
#include <iostream>
class MyClass
{
public:
int getI()
{
std::cout << "non-const getter" << std::endl;
return privateGetI<MyClass, int>(*this);
}
const int getI() const
{
std::cout << "const getter" << std::endl;
return privateGetI<const MyClass, const int>(*this);
}
private:
template <class C, typename T>
static T privateGetI(C c)
{
//do my stuff
return c._i;
}
int _i;
};
int main()
{
const MyClass myConstClass = MyClass();
myConstClass.getI();
MyClass myNonConstClass;
myNonConstClass.getI();
return 0;
}
This DDJ article shows a way using template specialization that doesn't require you to use const_cast. For such a simple function it really isn't needed though.
boost::any_cast (at one point, it doesn't any more) uses a const_cast from the const version calling the non-const version to avoid duplication. You can't impose const semantics on the non-const version though so you have to be very careful with that.
In the end some code duplication is okay as long as the two snippets are directly on top of each other.
To add to the solution jwfearn and kevin provided, here's the corresponding solution when the function returns shared_ptr:
struct C {
shared_ptr<const char> get() const {
return c;
}
shared_ptr<char> get() {
return const_pointer_cast<char>(static_cast<const C &>(*this).get());
}
shared_ptr<char> c;
};
Didn't find what I was looking for, so I rolled a couple of my own...
This one is a little wordy, but has the advantage of handling many overloaded methods of the same name (and return type) all at once:
struct C {
int x[10];
int const* getp() const { return x; }
int const* getp(int i) const { return &x[i]; }
int const* getp(int* p) const { return &x[*p]; }
int const& getr() const { return x[0]; }
int const& getr(int i) const { return x[i]; }
int const& getr(int* p) const { return x[*p]; }
template<typename... Ts>
auto* getp(Ts... args) {
auto const* p = this;
return const_cast<int*>(p->getp(args...));
}
template<typename... Ts>
auto& getr(Ts... args) {
auto const* p = this;
return const_cast<int&>(p->getr(args...));
}
};
If you have only one const method per name, but still plenty of methods to duplicate, then you might prefer this:
template<typename T, typename... Ts>
auto* pwrap(T const* (C::*f)(Ts...) const, Ts... args) {
return const_cast<T*>((this->*f)(args...));
}
int* getp_i(int i) { return pwrap(&C::getp_i, i); }
int* getp_p(int* p) { return pwrap(&C::getp_p, p); }
Unfortunately this breaks down as soon as you start overloading the name (the function pointer argument's argument list seems to be unresolved at that point, so it can't find a match for the function argument). Although you can template your way out of that, too:
template<typename... Ts>
auto* getp(Ts... args) { return pwrap<int, Ts...>(&C::getp, args...); }
But reference arguments to the const method fail to match against the apparently by-value arguments to the template and it breaks. Not sure why.Here's why.