<commit_before>/* value.tcc                                 -*- C++ -*-
   <NAME> (<EMAIL>), 25 Mar 2014
   FreeBSD-style copyright and disclaimer apply

   Template implementation for Value.
*/

#include "reflect.h"
#pragma once

namespace reflect {


/******************************************************************************/
/* VALUE                                                                      */
/******************************************************************************/

template<typename T>
Value::
Value(T&& value) :
    arg(Argument::make(std::forward<T>(value))),
    value_((void*)&value) // cast-away any const
{
    if (refType() != RefType::RValue) return;

    typedef typename std::decay<T>::type CleanT;
    storage.reset(value_ = new CleanT(std::move(value)));
}


template<typename T>
const T&
Value::
get() const
{
    return *static_cast<T*>(value_);
}


template<typename T>
bool
Value::
castable() const
{
    typedef typename CleanRef<T>::type Target;
    return !isVoid() && arg.isConvertibleTo<Target>();
}

template<typename T>
auto
Value::
cast() const -> typename CleanRef<T>::type
{
    if (!castable<T>()) {
        reflectError("<%s> is not castable to <%s>",
                arg.print(), printArgument<T>());
    }

    typedef typename std::decay<T>::type CleanT;
    return *static_cast<CleanT*>(value_);
}


template<typename T>
bool
Value::
copiable() const
{
    typedef typename CleanValue<T>::type Target;
    return !isVoid()
        && type()->isCopiable()
        && arg.isConvertibleTo<Target>();
}

template<typename T>
auto
Value::
copy() const -> typename CleanValue<T>::type
{
    if (!copiable<T>()) {
        reflectError("<%s> is not copiable to <%s>",
                arg.print(), printArgument<T>());
    }

    typedef typename std::decay<T>::type CleanT;
    return *static_cast<CleanT*>(value_);
}


template<typename T>
bool
Value::
movable() const
{
    typedef typename CleanValue<T>::type Target;
    return !isVoid()
        && type()->isMovable()
        && !arg.isConst()
        && arg.isConvertibleTo<Target>()
        && (!storage || storage.unique());
}

template<typename T>
auto
Value::
move() -> typename CleanValue<T>::type
{
    if (!movable<T>()) {
        reflectError("<%s> is not movable to <%s>",
                arg.print(), printArgument<T>());
    }

    typedef typename std::decay<T>::type CleanT;

    CleanT value = std::move(*static_cast<CleanT*>(value_));
    *this = Value();
    return value;
}


} // reflect<commit_msg>Tweak.<commit_after>/* value.tcc                                 -*- C++ -*-
   <NAME> (<EMAIL>), 25 Mar 2014
   FreeBSD-style copyright and disclaimer apply

   Template implementation for Value.
*/

#include "reflect.h"
#pragma once

namespace reflect {


/******************************************************************************/
/* VALUE                                                                      */
/******************************************************************************/

template<typename T>
Value::
Value(T&& value) :
    arg(Argument::make(std::forward<T>(value))),
    value_((void*)&value) // cast-away any const
{
    if (refType() != RefType::RValue) return;

    typedef typename std::decay<T>::type CleanT;
    storage.reset(value_ = new CleanT(std::move(value)));
}


template<typename T>
const T&
Value::
get() const
{
    return *static_cast<T*>(value_);
}


template<typename T>
bool
Value::
castable() const
{
    typedef typename CleanRef<T>::type Target;
    return !isVoid() && arg.isConvertibleTo<Target>();
}

template<typename T>
auto
Value::
cast() const -> typename CleanRef<T>::type
{
    if (!castable<T>()) {
        reflectError("<%s> is not castable to <%s>",
                arg.print(), printArgument<T>());
    }

    typedef typename std::decay<T>::type CleanT;
    return *static_cast<CleanT*>(value_);
}


template<typename T>
bool
Value::
copiable() const
{
    typedef typename CleanValue<T>::type Target;
    return !isVoid()
        && type()->isCopiable()
        && arg.isConvertibleTo<Target>();
}

template<typename T>
auto
Value::
copy() const -> typename CleanValue<T>::type
{
    if (!copiable<T>()) {
        reflectError("<%s> is not copiable to <%s>",
                arg.print(), printArgument<T>());
    }

    typedef typename std::decay<T>::type CleanT;
    return *static_cast<CleanT*>(value_);
}


template<typename T>
bool
Value::
movable() const
{
    typedef typename CleanValue<T>::type Target;
    return !isVoid()
        && type()->isMovable()
        && !isConst()
        && arg.isConvertibleTo<Target>()
        && (!storage || storage.unique());
}

template<typename T>
auto
Value::
move() -> typename CleanValue<T>::type
{
    if (!movable<T>()) {
        reflectError("<%s> is not movable to <%s>",
                arg.print(), printArgument<T>());
    }

    typedef typename std::decay<T>::type CleanT;

    CleanT value = std::move(*static_cast<CleanT*>(value_));
    *this = Value();
    return value;
}


} // reflect
{'fraction_non_alphanumeric': 0.22191400832177532, 'fraction_numerical': 0.0023776500891618782, 'mean_word_length': 3.094079480940795, 'pattern_counts': {'":': 0, '<': 83, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5235420', 'n_tokens_mistral': 1550, 'n_tokens_neox': 1475, 'n_words': 349}