cppast/include/cppast/cpp_member_function.hpp
2017-03-25 14:34:04 +01:00

335 lines
10 KiB
C++

// Copyright (C) 2017 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.
#ifndef CPPAST_CPP_MEMBER_FUNCTION_HPP_INCLUDED
#define CPPAST_CPP_MEMBER_FUNCTION_HPP_INCLUDED
#include <type_safe/flag_set.hpp>
#include <cppast/cpp_function.hpp>
namespace cppast
{
/// The `virtual`-ness of a member function.
///
/// This is a [ts::flag_set]() `enum`.
/// \notes It does not specify whether a member function is `virtual` or not,
/// only the kind of `virtual`.
/// \notes As surprising as it may be, any of these can be used in combination,
/// i.e. you can have a `final` non-overriding function or an overriding pure `virtual` function.
enum class cpp_virtual_flags
{
pure, //< Set if the function is pure.
override, //< Set if the function overrides a base class function.
final, //< Set if the function is marked `final`.
};
} // namespace cppast
/// \exclude
namespace type_safe
{
template <>
struct flag_set_traits<cppast::cpp_virtual_flags> : std::true_type
{
static constexpr std::size_t size() noexcept
{
return 3u;
}
};
} // namespace type_safe
namespace cppast
{
/// The `virtual` information of a member function.
///
/// This is an optional of the combination of the [cppast::cpp_virtual_flags]().
/// If the optional has a value, the member function is `virtual`,
/// and the [ts::flag_set]() describes additional information.
using cpp_virtual = type_safe::optional<type_safe::flag_set<cpp_virtual_flags>>;
/// \returns Whether or not a member function is `virtual`.
inline bool is_virtual(const cpp_virtual& virt) noexcept
{
return virt.has_value();
}
/// \returns Whether or not a member function is pure.
inline bool is_pure(const cpp_virtual& virt) noexcept
{
return static_cast<bool>(virt.value_or(cpp_virtual_flags::final) & cpp_virtual_flags::pure);
}
/// \returns Whether or not a member function overrides another one.
inline bool is_overriding(const cpp_virtual& virt) noexcept
{
return static_cast<bool>(virt.value_or(cpp_virtual_flags::pure)
& cpp_virtual_flags::override);
}
/// \returns Whether or not a member function is `final`.
inline bool is_final(const cpp_virtual& virt) noexcept
{
return static_cast<bool>(virt.value_or(cpp_virtual_flags::pure) & cpp_virtual_flags::final);
}
/// Base classes for all regular member function.
///
/// The two derived classes are [cppast::cpp_member_function]() and [cppast::cpp_conversion_op]().
class cpp_member_function_base : public cpp_function_base
{
public:
/// \returns The return type of the member function.
const cpp_type& return_type() const noexcept
{
return *return_type_;
}
/// \returns Whether or not it is `virtual`.
bool is_virtual() const noexcept
{
return virtual_info().has_value();
}
/// \returns The `virtual`-ness of the member function.
const cpp_virtual& virtual_info() const noexcept
{
return virtual_;
}
/// \returns The cv-qualifier on the member function.
cpp_cv cv_qualifier() const noexcept
{
return cv_;
}
/// \returns The ref-qualifier on the member function.
cpp_reference ref_qualifier() const noexcept
{
return ref_;
}
/// \returns Whether or not the member function is `constexpr`.
bool is_constexpr() const noexcept
{
return constexpr_;
}
protected:
/// Builder class for member functions.
template <typename T>
class basic_member_builder : public basic_builder<T>
{
public:
/// \effects Sets the name and return type.
basic_member_builder(std::string name, std::unique_ptr<cpp_type> return_type)
{
this->function = std::unique_ptr<T>(new T(std::move(name), std::move(return_type)));
}
/// \effects Sets the cv- and ref-qualifier.
void cv_ref_qualifier(cpp_cv cv, cpp_reference ref) noexcept
{
auto& base = static_cast<cpp_member_function_base&>(*this->function);
base.cv_ = cv;
base.ref_ = ref;
}
/// \effects Sets the `virtual`-ness of the function.
void virtual_info(type_safe::flag_set<cpp_virtual_flags> virt) noexcept
{
static_cast<cpp_member_function_base&>(*this->function).virtual_ = virt;
}
/// \effects Marks the function as `constexpr`.
void is_constexpr() noexcept
{
static_cast<cpp_member_function_base&>(*this->function).constexpr_ = true;
}
protected:
basic_member_builder() noexcept = default;
};
/// \effects Sets name and return type, as well as the rest to defaults.
cpp_member_function_base(std::string name, std::unique_ptr<cpp_type> return_type)
: cpp_function_base(std::move(name)),
return_type_(std::move(return_type)),
cv_(cpp_cv_none),
ref_(cpp_ref_none),
constexpr_(false)
{
}
private:
std::unique_ptr<cpp_type> return_type_;
cpp_virtual virtual_;
cpp_cv cv_;
cpp_reference ref_;
bool constexpr_;
};
/// A [cppast::cpp_entity]() modelling a member function.
class cpp_member_function final : public cpp_member_function_base
{
public:
static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_member_function]().
class builder : public cpp_member_function_base::basic_member_builder<cpp_member_function>
{
public:
using cpp_member_function_base::basic_member_builder<cpp_member_function>::
basic_member_builder;
};
private:
using cpp_member_function_base::cpp_member_function_base;
cpp_entity_kind do_get_entity_kind() const noexcept override;
friend basic_member_builder<cpp_member_function>;
};
/// A [cppast::cpp_entity]() modelling a C++ conversion operator.
class cpp_conversion_op final : public cpp_member_function_base
{
public:
static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_conversion_op]().
class builder : public basic_member_builder<cpp_conversion_op>
{
public:
using basic_member_builder::basic_member_builder;
/// \effects Marks the conversion operator `explicit`.
void is_explicit() noexcept
{
function->explicit_ = true;
}
private:
using basic_member_builder::is_variadic;
using basic_member_builder::add_parameter;
};
/// \returns Whether or not the conversion is `explicit`.
bool is_explicit() const noexcept
{
return explicit_;
}
private:
cpp_conversion_op(std::string name, std::unique_ptr<cpp_type> return_t)
: cpp_member_function_base(std::move(name), std::move(return_t)), explicit_(false)
{
}
cpp_entity_kind do_get_entity_kind() const noexcept override;
bool explicit_;
friend basic_member_builder<cpp_conversion_op>;
};
/// A [cppast::cpp_entity]() modelling a C++ constructor.
class cpp_constructor final : public cpp_function_base
{
public:
static cpp_entity_kind kind() noexcept;
/// Builder for [cppast::cpp_constructor]().
class builder : public basic_builder<cpp_constructor>
{
public:
using basic_builder::basic_builder;
/// \effects Marks the constructor `explicit`.
void is_explicit() noexcept
{
function->explicit_ = true;
}
/// \effects Marks the constructor `constexpr`.
void is_constexpr() noexcept
{
function->constexpr_ = true;
}
};
/// \returns Whether or not the constructor is `explicit`.
bool is_explicit() const noexcept
{
return explicit_;
}
/// \returns Whether or not the constructor is `constexpr`.
bool is_constexpr() const noexcept
{
return constexpr_;
}
private:
cpp_constructor(std::string name)
: cpp_function_base(std::move(name)), explicit_(false), constexpr_(false)
{
}
cpp_entity_kind do_get_entity_kind() const noexcept override;
bool explicit_;
bool constexpr_;
friend basic_builder<cpp_constructor>;
};
/// A [cppast::cpp_entity]() modelling a C++ destructor.
class cpp_destructor final : public cpp_function_base
{
public:
static cpp_entity_kind kind() noexcept;
/// Builds a [cppast::cpp_destructor]().
class builder : public basic_builder<cpp_destructor>
{
public:
using basic_builder::basic_builder;
/// \effects Sets the `virtual`-ness of the destructor.
void virtual_info(cpp_virtual virt) noexcept
{
function->virtual_ = virt;
}
private:
using basic_builder::add_parameter;
using basic_builder::is_variadic;
};
/// \returns Whether or not it is `virtual`.
bool is_virtual() const noexcept
{
return virtual_info().has_value();
}
/// \returns The `virtual`-ness of the constructor.
cpp_virtual virtual_info() const noexcept
{
return virtual_;
}
private:
cpp_destructor(std::string name) : cpp_function_base(std::move(name))
{
}
cpp_entity_kind do_get_entity_kind() const noexcept override;
cpp_virtual virtual_;
friend basic_builder<cpp_destructor>;
};
} // namespace cppast
#endif // CPPAST_CPP_MEMBER_FUNCTION_HPP_INCLUDED