Skip to content

Instantly share code, notes, and snippets.

@plasma-effect
Last active June 3, 2019 07:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save plasma-effect/0181a772f971329390091d71fa54fdda to your computer and use it in GitHub Desktop.
Save plasma-effect/0181a772f971329390091d71fa54fdda to your computer and use it in GitHub Desktop.
#pragma once
#include<type_traits>
// copyright (c) 2019 plasma-effect
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt)
namespace auto_indexer
{
enum
{
set = 1,
get = 2
};
template<class Derived, class T, int flag = set | get>class indexer
{
template<int flag>class return_t
{
friend class indexer<Derived, T, flag>;
static_assert(0 < flag&& flag < 4, "flag error");
return_t(Derived* p, std::size_t i)
{
}
};
template<>class return_t<set>
{
friend class indexer<Derived, T, flag>;
Derived* ptr;
std::size_t index;
return_t(Derived* p, std::size_t i) :ptr(p), index(i)
{
}
public:
decltype(auto) operator=(T&& value)
{
return ptr->set(index, std::move(value));
}
decltype(auto) operator=(T const& value)
{
return ptr->set(index, value);
}
};
template<>class return_t<get>
{
friend class indexer<Derived, T, flag>;
Derived const* ptr;
std::size_t index;
return_t(Derived const* p, std::size_t i) :ptr(p), index(i)
{
}
public:
operator T()const
{
return ptr->get(index);
}
};
template<>class return_t<set | get>
{
friend class indexer<Derived, T, flag>;
Derived* ptr;
std::size_t index;
return_t(Derived* p, std::size_t i) :ptr(p), index(i)
{
}
public:
decltype(auto) operator=(T&& value)
{
return ptr->set(index, std::move(value));
}
decltype(auto) operator=(T const& value)
{
return ptr->set(index, value);
}
operator T()const
{
return ptr->get(index);
}
};
public:
auto operator[](std::size_t index)
{
if constexpr (flag == get)
{
return return_t<get>(static_cast<Derived const*>(this), index);
}
else
{
return return_t<flag>(static_cast<Derived*>(this), index);
}
}
auto operator[](std::size_t index)const
{
if constexpr (flag & get)
{
return return_t<get>(static_cast<Derived const*>(this), index);
}
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment