Why is func_getter class provided below is not assignable?
#include <type_traits>
#include <string>
template <class T, class ReturnType>
using FuncPtr = ReturnType(T::*)() const;
template <class T, class ReturnType>
class func_getter
{
public:
using MyFuncPtr = FuncPtr<T, ReturnType>;
constexpr func_getter(MyFuncPtr p) : m_p(p) {}
func_getter(const func_getter&) = default;
func_getter(func_getter&&) = default;
func_getter& operator = (const func_getter&) = default;
func_getter& operator = (func_getter&&) = default;
constexpr ReturnType operator() (const T& val) const
{
return (val.*m_p)();
}
private:
MyFuncPtr m_p;
};
struct X
{
int a;
std::string b;
int GetA() const
{
return a;
}
int GetA1() const
{
return a;
}
};
using GetAPtr = FuncPtr<X, int>;
static_assert(std::is_copy_constructible_v<GetAPtr>);
static_assert(std::is_copy_assignable_v<GetAPtr>);
static_assert(std::is_move_constructible_v<GetAPtr>);
static_assert(std::is_move_assignable_v<GetAPtr>);
inline constexpr auto a_getter = func_getter(&X::GetA);
static_assert(std::is_copy_constructible_v<decltype(a_getter)>);
static_assert(std::is_move_constructible_v<decltype(a_getter)>);
all the above static_asserts do not fail, but the following fail (at least with MSVC2022):
static_assert(std::is_copy_assignable_v<decltype(a_getter)>);
static_assert(std::is_move_assignable_v<decltype(a_getter)>);
why?
>Solution :
decltype(a_getter) is not just GetAPtr. a_getter is constexpr, hence const, and cannot be assigned to.
If you want to infer GetAptr from a_getter you can use std::remove_const_t or std::decay_t (https://godbolt.org/z/7qvhaqxeW).