Skip to content

Latest commit

 

History

History
508 lines (392 loc) · 9.2 KB

Access.md

File metadata and controls

508 lines (392 loc) · 9.2 KB

Access

Access to an object of a token is available by the following methods.

  1. One token
    1. Single
    2. Optional
      1. Classic "if-else"
        1. Dereferenceable
        2. Proxy accessible
      2. Unified "if-else"
      3. Unified lambda
      4. Range-based "for"
  2. Several tokens
    1. Single
    2. Optional
      1. Classic "if-else"
        1. Dereferenceable
        2. Proxy accessible
      2. Unified "if-else"
      3. Unified lambda

Note: Prefer to use the operator*() rather than the operator->() of an otn token, since it is designed as an object token not as a pointer to an object at some address. The operator->() may be deprecated and removed in the future.

One token

Single

A single token must always refer to an object, there is no need to check it, it can be accessed directly.

Example
#include <otn/all.hpp>
#include <iostream>

template <class Single>
void print(const Single& token)
{
    std::cout << "object: " << *token << std::endl;
}

int main()
{
    using namespace otn;

    unique<int>    a{itself, 7};
    raw::weak<int> b = a;

    print(a);
    print(b);
}

Output:

object: 7
object: 7

Optional

An optional token may be empty, it must be checked before accessing.

Classic "if-else"

Dereferenceable

A dereferenceable token can be accessed directly, after check. This method does not work with non-dereferenceable tokens.

Example
#include <otn/all.hpp>
#include <iostream>

template <class Optional>
void print(const Optional& token)
{
    if (token)
        std::cout << "object: " << *token << std::endl;
    else
        std::cout << "token is empty" << std::endl;
}

int main()
{
    using namespace otn;

    unique_optional<int>    a{itself, 7};
    weak_optional<int>      b = a;
    raw::weak_optional<int> c = a;
    raw::weak_optional<int> d;

    print(a);
    // print(b); // Error: the safe::weak_optional is not dereferenceable.
    print(c);
    print(d);
}

Output:

object: 7
object: 7
token is empty

Proxy accessible

Some tokens are not dereferenceable (safe::weak_optional, std::weak_ptr). Such tokens can be accessed by a proxy.

Example
#include <otn/all.hpp>
#include <iostream>

template <class ProxyAccessible>
void print(const ProxyAccessible& token)
{
    if (otn::unified_optional<int> loc = token)
        std::cout << "object: " << *loc << std::endl;
    else
        std::cout << "token is empty" << std::endl;
}

int main()
{
    using namespace otn;

    unique_optional<int> a{itself, 7};
    weak_optional<int>   b = a;
    weak_optional<int>   c;

    print(b);
    print(c);
}

Output:

object: 7
token is empty

Unified "if-else"

The otn::gain function provides unified optimized access to any token type. It returns a list of a proxy, which can be bound to variables by structured binding, after check. The proxy list can be dereferenced to access tokens' objects, after check.

Example
#include <otn/all.hpp>
#include <iostream>

template <class Optional>
void print(const Optional& token)
{
    if (auto loc = otn::gain(token))
        std::cout << "object: " << *loc << std::endl;
    else
        std::cout << "token is empty" << std::endl;
}

int main()
{
    using namespace otn;

    unique_optional<int>    a{itself, 7};
    weak_optional<int>      b = a;
    raw::weak_optional<int> c = a;
    raw::weak_optional<int> d;

    print(a);
    print(b);
    print(c);
    print(d);
}

Output:

object: 7
object: 7
object: 7
token is empty

Unified lambda

The otn::access function provides unified optimized access to any token type. It checks tokens and passes they object references to the lambda.

Example
#include <otn/all.hpp>
#include <iostream>

template <class Optional>
void print(const Optional& token)
{
    otn::access(token, [](auto& object)
    { std::cout << "object: " << object << std::endl; },
    [] // else
    { std::cout << "token is empty" << std::endl; });
}

int main()
{
    using namespace otn;

    unique_optional<int>    a{itself, 7};
    weak_optional<int>      b = a;
    raw::weak_optional<int> c = a;
    raw::weak_optional<int> d;

    print(a);
    print(b);
    print(c);
    print(d);
}

Output:

object: 7
object: 7
object: 7
token is empty

Range-based "for"

otn tokens meet the requirements of std::ranges::range, they can be accessed by range-based for loop.

Example
#include <otn/all.hpp>
#include <iostream>

template <class Token>
void print(const Token& token)
{
    for (auto& token : token)
        std::cout << "object: " << *token << std::endl;
}

int main()
{
    using namespace otn;

    unique_single<int>      a{itself, 7};
    weak_optional<int>      b = a;
    raw::weak_single<int>   c = a;
    raw::weak_optional<int> d;

    print(a);
    print(b);
    print(c);
    print(d);
}

Output:

object: 7
object: 7
object: 7

Several tokens

Single

Example
#include <otn/all.hpp>
#include <iostream>

template <class SingleA, class SingleB>
void calc(const SingleA& a, const SingleB& b)
{
    std::cout << "result: " << *a + *b << std::endl;
}

int main()
{
    using namespace otn;

    unique<int>    a{itself, 7};
    shared<int>    b{itself, 3};
    raw::weak<int> c = a;

    calc(a, b);
    calc(b, c);
}

Output:

result: 10
result: 10

Optional

Classic "if-else"

Dereferenceable

Example
#include <otn/all.hpp>
#include <iostream>

template <class OptionalA, class OptionalB>
void calc(const OptionalA& a, const OptionalB& b)
{
    if (a && b)
        std::cout << "result: " << *a + *b << std::endl;
    else
        std::cout << "invalid arguments" << std::endl;
}

int main()
{
    using namespace otn;

    unique_optional<int>    a{itself, 7};
    shared_optional<int>    b{itself, 3};
    weak_optional<int>      c = a;
    raw::weak_optional<int> d = a;
    raw::weak_optional<int> e;

    calc(a, b);
    // calc(b, c); // Error: the safe::weak_optional is not dereferenceable.
    calc(d, e);
}

Output:

result: 10
invalid arguments

Proxy accessible

Example
#include <otn/all.hpp>
#include <iostream>

template <class ProxyAccessibleA, class ProxyAccessibleB>
void calc(const ProxyAccessibleA& a, const ProxyAccessibleB& b)
{
    if (otn::unified_optional<int> loc_a = a)
        if (otn::unified_optional<int> loc_b = b)
        {
            std::cout << "result: " << *loc_a + *loc_b << std::endl;
            return;
        }

    std::cout << "invalid arguments" << std::endl;
}

int main()
{
    using namespace otn;

    unique_optional<int> a{itself, 7};
    shared_optional<int> b{itself, 3};
    weak_optional<int>   c = a;
    weak_optional<int>   d = b;
    weak_optional<int>   e;

    calc(c, d);
    calc(d, e);
}

Output:

result: 10
invalid arguments

Unified "if-else"

Example
#include <otn/all.hpp>
#include <iostream>

template <class OptionalA, class OptionalB>
void calc(const OptionalA& a, const OptionalB& b)
{
    if (auto locs = otn::gain(a, b))
    {
        auto& [a, b] = *locs;
        std::cout << "result: " << a + b << std::endl;
    }
    else
    {
        std::cout << "invalid arguments" << std::endl;
    }
}

int main()
{
    using namespace otn;

    unique_optional<int>    a{itself, 7};
    shared_optional<int>    b{itself, 3};
    weak_optional<int>      c = a;
    raw::weak_optional<int> d = a;
    raw::weak_optional<int> e;

    calc(a, b);
    calc(b, c);
    calc(d, e);
}

Output:

result: 10
result: 10
invalid arguments

Unified lambda

Example
#include <otn/all.hpp>
#include <iostream>

template <class OptionalA, class OptionalB>
void calc(const OptionalA& a, const OptionalB& b)
{
    otn::access(a, b, [](auto& a, auto& b)
    {
        std::cout << "result: " << a + b << std::endl;
    },
    [] // else
    {
        std::cout << "invalid arguments" << std::endl;
    });
}

int main()
{
    using namespace otn;

    unique_optional<int>    a{itself, 7};
    shared_optional<int>    b{itself, 3};
    weak_optional<int>      c = a;
    raw::weak_optional<int> d = a;
    raw::weak_optional<int> e;

    calc(a, b);
    calc(b, c);
    calc(d, e);
}

Output:

result: 10
result: 10
invalid arguments