Skip to content

Commit

Permalink
Fix subscript return types.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmadden committed Aug 8, 2018
1 parent b9cc52d commit aaf983a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 47 deletions.
24 changes: 4 additions & 20 deletions src/alia/signals/operators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,28 +377,13 @@ struct has_at_indexer<
{
};

// has_const_subscript<Container, Index>::value yields a compile-time boolean
// indicating whether or not Container has a const subscript operator that takes
// an Index.
template<class Container, class Index, class = void_t<>>
struct has_const_subscript : std::false_type
{
};
template<class Container, class Index>
struct has_const_subscript<
Container,
Index,
void_t<decltype(std::declval<Container const&>()[std::declval<Index>()])>>
: std::true_type
{
};

template<class Container, class Index>
auto
invoke_const_subscript(
Container const& container,
Index const& index,
std::enable_if_t<has_const_subscript<Container, Index>::value>* = 0)
std::enable_if_t<!has_at_indexer<Container, Index>::value>* = 0)
-> decltype(container[index])
{
return container[index];
}
Expand All @@ -408,9 +393,8 @@ auto
invoke_const_subscript(
Container const& container,
Index const& index,
std::enable_if_t<
!has_const_subscript<Container, Index>::value
&& has_at_indexer<Container, Index>::value>* = 0)
std::enable_if_t<has_at_indexer<Container, Index>::value>* = 0)
-> decltype(container.at(index))
{
return container.at(index);
}
Expand Down
85 changes: 58 additions & 27 deletions unit_tests/signals/operators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,59 @@ TEST_CASE("field signal", "[signals]")
REQUIRE(f.y == 0.5);
}

struct my_array
{
int x[3] = {1, 2, 3};
int& operator[](int i)
{
return x[i];
}
int const& operator[](int i) const
{
return x[i];
}
};

struct my_const_array
{
int x[3] = {1, 2, 3};
int operator[](int i) const
{
return x[i];
}
};

// Test some of the helper metafunctions for subscript signals.
TEST_CASE("subscript metafunctions", "[signals]")
{
REQUIRE(has_at_indexer<std::vector<int>, int>::value);
REQUIRE(has_at_indexer<std::map<int, int>, int>::value);
REQUIRE(has_at_indexer<std::vector<bool>, int>::value);
REQUIRE(!has_at_indexer<my_array, int>::value);
REQUIRE(!has_at_indexer<my_const_array, int>::value);

REQUIRE((std::is_same<
subscript_result_type<std::vector<float>, int>::type,
float>::value));
REQUIRE((std::is_same<
subscript_result_type<std::map<int, float>, int>::type,
float>::value));
REQUIRE((std::is_same<
subscript_result_type<std::vector<bool>, int>::type,
bool>::value));
REQUIRE(
(std::is_same<subscript_result_type<my_array, int>::type, int>::value));
REQUIRE(
(std::is_same<subscript_result_type<my_const_array, int>::type, int>::
value));

REQUIRE(const_subscript_returns_reference<std::vector<int>, int>::value);
REQUIRE(const_subscript_returns_reference<std::map<int, int>, int>::value);
REQUIRE(!const_subscript_returns_reference<std::vector<bool>, int>::value);
REQUIRE(const_subscript_returns_reference<my_array, int>::value);
REQUIRE(!const_subscript_returns_reference<my_const_array, int>::value);
}

TEST_CASE("vector subscript", "[signals]")
{
using namespace alia;
Expand Down Expand Up @@ -255,8 +308,8 @@ TEST_CASE("vector subscript", "[signals]")
write_signal(s, 1);
REQUIRE(c == std::vector<int>({2, 1, 3}));

// Check that changes in the container and the index both cause changes in
// the value ID.
// Check that changes in the container and the index both cause changes
// in the value ID.
REQUIRE(!original_id.matches(s.value_id()));
auto t = c_signal[value(0)];
REQUIRE(t.value_id() != s.value_id());
Expand Down Expand Up @@ -340,25 +393,12 @@ TEST_CASE("map subscript", "[signals]")

TEST_CASE("custom ref subscript", "[signals]")
{
struct my_vector
{
int x[3] = {1, 2, 3};
int& operator[](int i)
{
return x[i];
}
int const& operator[](int i) const
{
return x[i];
}
};

my_vector c;
my_array c;
auto c_signal = lambda_bidirectional(
always_readable,
[&]() { return c; },
always_writable,
[&](my_vector const& v) { c = v; },
[&](my_array const& v) { c = v; },
[&]() {
return unit_id; // doesn't really matter
});
Expand All @@ -378,16 +418,7 @@ TEST_CASE("custom ref subscript", "[signals]")

TEST_CASE("custom by-value subscript", "[signals]")
{
struct my_vector
{
int x[3] = {1, 2, 3};
int operator[](int i) const
{
return x[i];
}
};

my_vector c;
my_const_array c;
auto c_signal = lambda_input(
always_readable,
[&]() { return c; },
Expand Down

0 comments on commit aaf983a

Please sign in to comment.