Skip to content

Commit

Permalink
[FIX] travis: gcc-7.2 bug
Browse files Browse the repository at this point in the history
  • Loading branch information
marehr committed Feb 20, 2018
1 parent 1ffa3f3 commit bafac27
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 15 deletions.
5 changes: 0 additions & 5 deletions include/seqan3/range/container/concatenated_sequences.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1305,8 +1305,3 @@ class concatenated_sequences
};

} // namespace seqan3

#ifndef NDEBUG
static_assert(seqan3::reservable_sequence_concept<seqan3::concatenated_sequences<std::string>>);
static_assert(seqan3::forward_range_concept<seqan3::concatenated_sequences<std::string>>);
#endif
68 changes: 59 additions & 9 deletions include/seqan3/range/container/concept.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,50 @@

#include <initializer_list>

// remove if sequence_concept_modified_by_const_iterator_bug vanished from travis
#include <string>

namespace seqan3::detail
{
//!\privatesection

/*!\interface seqan3::sequence_concept_modified_by_const_iterator <>
* \brief Can insert and erase used with const iterators
*/
//!\cond
template <typename type>
concept bool sequence_concept_modified_by_const_iterator = requires (type val, type val2)
{
{ val.insert(val.cbegin(), val2.front()) } -> typename type::iterator;
{ val.insert(val.cbegin(), typename type::value_type{}) } -> typename type::iterator;
{ val.insert(val.cbegin(), typename type::size_type{}, typename type::value_type{})} -> typename type::iterator;
{ val.insert(val.cbegin(), val2.begin(), val2.end()) } -> typename type::iterator;
//TODO should return type::iterator on strings (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83328)
{ val.insert(val.cbegin(), std::initializer_list<typename type::value_type>{}) };
{ val.erase(val.cbegin()) } -> typename type::iterator;
{ val.erase(val.cbegin(), val.cend()) } -> typename type::iterator;

{ val.insert(val.begin(), typename type::size_type{}, typename type::value_type{}) } -> typename type::iterator;
{ val.insert(val.begin(), val2.begin(), val2.end()) } -> typename type::iterator;
};
//!\endcond

/*!\brief Workaround for a travis-ci exclusive bug with g++-7.2.
*
* seqan3::detail::sequence_concept_modified_by_const_iterator<std::string> is
* known to work, but travis-ci has version of g++-7.2 where a bug in the
* STL prevents this concept to be true.
*
* \attention This workaround can be removed if container_concept_test is not
* failing on travis anymore.
*/
constexpr bool sequence_concept_modified_by_const_iterator_bug
= sequence_concept_modified_by_const_iterator<std::string> == false;

//!\publicsection

} // seqan3::detail

namespace seqan3
{

Expand Down Expand Up @@ -127,15 +171,21 @@ concept bool sequence_concept = requires (type val, type val2)

// modify container
//TODO: how do you model this?
// { val.emplace(typename type::const_iterator{}, ? } -> typename type::iterator;
{ val.insert(val.cbegin(), val2.front()) } -> typename type::iterator;
{ val.insert(val.cbegin(), typename type::value_type{}) } -> typename type::iterator;
{ val.insert(val.cbegin(), typename type::size_type{}, typename type::value_type{})} -> typename type::iterator;
{ val.insert(val.cbegin(), val2.begin(), val2.end()) } -> typename type::iterator;
//TODO this fails on std::string, although it should work
// { val.insert(val.cbegin(), std::initializer_list<typename type::value_type>{}) } -> typename type::iterator;
{ val.erase(val.cbegin()) } -> typename type::iterator;
{ val.erase(val.cbegin(), val.cend()) } -> typename type::iterator;
// { val.emplace(typename type::const_iterator{}, ? } -> typename type::iterator;

{ val.insert(val.begin(), val2.front()) } -> typename type::iterator;
{ val.insert(val.begin(), typename type::value_type{}) } -> typename type::iterator;
// because of a travis bug we can't assume typename type::iterator as return type
{ val.insert(val.begin(), typename type::size_type{}, typename type::value_type{}) };
{ val.insert(val.begin(), val2.begin(), val2.end()) };
//TODO should return type::iterator on strings (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83328)
{ val.insert(val.begin(), std::initializer_list<typename type::value_type>{}) };
{ val.erase(val.begin()) } -> typename type::iterator;
{ val.erase(val.begin(), val.end()) } -> typename type::iterator;

// workaround a travis bug where insert/erase can't take a const iterator, e.g. cbegin()
requires detail::sequence_concept_modified_by_const_iterator_bug || detail::sequence_concept_modified_by_const_iterator<type>;

{ val.push_back(val.front()) } -> void;
{ val.push_back(typename type::value_type{}) } -> void;
{ val.pop_back() } -> void;
Expand Down
161 changes: 160 additions & 1 deletion test/range/container/container_concept_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,25 @@
#include <deque>
#include <string>

#include <seqan3/range/container/all.hpp>
#include <seqan3/range/container/concept.hpp>
#include <seqan3/range/container/concatenated_sequences.hpp>

using namespace seqan3;

TEST(range_concept, forward_range_concept)
{
EXPECT_TRUE((seqan3::forward_range_concept<std::array<char, 2>>));
EXPECT_TRUE((seqan3::forward_range_concept<std::list<char>>));
EXPECT_TRUE((seqan3::forward_range_concept<std::forward_list<char>>)); // `.size()` missing
EXPECT_TRUE((seqan3::forward_range_concept<seqan3::concatenated_sequences<std::vector<char>>>));
EXPECT_TRUE((seqan3::forward_range_concept<std::vector<char>>));
EXPECT_TRUE((seqan3::forward_range_concept<std::deque<char>>));
EXPECT_TRUE((seqan3::forward_range_concept<std::string>));

EXPECT_TRUE((seqan3::forward_range_concept<seqan3::concatenated_sequences<std::string>>));
EXPECT_TRUE((seqan3::forward_range_concept<seqan3::concatenated_sequences<std::vector<char>>>));
}

TEST(container_concept, container_concept)
{
EXPECT_TRUE((seqan3::container_concept<std::array<char, 2>>));
Expand All @@ -53,6 +68,132 @@ TEST(container_concept, container_concept)
EXPECT_TRUE((seqan3::container_concept<std::vector<char>>));
EXPECT_TRUE((seqan3::container_concept<std::deque<char>>));
EXPECT_TRUE((seqan3::container_concept<std::string>));

EXPECT_TRUE((seqan3::container_concept<seqan3::concatenated_sequences<std::string>>));
EXPECT_TRUE((seqan3::container_concept<seqan3::concatenated_sequences<std::vector<char>>>));
}

template <typename string_t>
void container_concept_travis_bug_test()
{
// non const version of container_concept_const_travis_bug_test
using namespace std::string_literals;

// example code from http://en.cppreference.com/w/cpp/string/basic_string/insert
string_t s = "xmplr";
string_t r = "";
typename string_t::iterator it;

// insert(size_type index, size_type count, char ch)
r = s.insert(0, 1, 'E');
EXPECT_EQ("Exmplr", s);

// insert(size_type index, const char* s)
r = s.insert(2, "e");
EXPECT_EQ("Exemplr", s);

// insert(size_type index, string const& str)
r = s.insert(6, "a"s);
EXPECT_EQ("Exemplar", s);

// insert(size_type index, string const& str,
// size_type index_str, size_type count)
r = s.insert(8, " is an example string."s, 0, 14);
EXPECT_EQ("Exemplar is an example", s);

// insert(const_iterator pos, char ch)
it = s.insert(s.begin() + s.find_first_of('n') + 1, ':');
EXPECT_EQ("Exemplar is an: example", s);

// insert(const_iterator pos, size_type count, char ch)
//TODO should return type::iterator on strings, remove if
// sequence_concept_modified_by_const_iterator_bug is no issue anymore
// it =
s.insert(s.begin() + s.find_first_of(':') + 1, 2, '=');
EXPECT_EQ("Exemplar is an:== example", s);

// insert(const_iterator pos, InputIt first, InputIt last)
{
string_t seq = " string";
//TODO should return type::iterator on strings, remove if
// sequence_concept_modified_by_const_iterator_bug is no issue anymore
// it =
s.insert(s.begin() + s.find_last_of('e') + 1,
std::begin(seq), std::end(seq));
EXPECT_EQ("Exemplar is an:== example string", s);
}

// insert(const_iterator pos, std::initializer_list<char>)
//TODO should return type::iterator on strings (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83328)
// it =
s.insert(s.begin() + s.find_first_of('g') + 1, { '.' });
EXPECT_EQ("Exemplar is an:== example string.", s);
}

template <typename string_t>
void container_concept_const_travis_bug_test()
{
// travis failed on this statement
// concept bool sequence_concept = requires (type val, type val2)
// ^~~~~~~~~~~~~~~~
// /include/seqan3/range/container/concept.hpp:113:14: note: with ‘std::basic_string<char> val’
// /include/seqan3/range/container/concept.hpp:113:14: note: with ‘std::basic_string<char> val2’
// [...]
// /include/seqan3/range/container/concept.hpp:113:14: note: the required expression ‘val.erase(val.cbegin(), val.cend())’ would be ill-formed

using namespace std::string_literals;

static_assert(detail::sequence_concept_modified_by_const_iterator<string_t>);
static_assert(!detail::sequence_concept_modified_by_const_iterator_bug && std::is_same_v<string_t, std::string>);
static_assert(seqan3::container_concept<string_t>);

// example code from http://en.cppreference.com/w/cpp/string/basic_string/insert
string_t s = "xmplr";

// insert(size_type index, size_type count, char ch)
s.insert(0, 1, 'E');
EXPECT_EQ("Exmplr", s);

// insert(size_type index, const char* s)
s.insert(2, "e");
EXPECT_EQ("Exemplr", s);

// insert(size_type index, string const& str)
s.insert(6, "a"s);
EXPECT_EQ("Exemplar", s);

// insert(size_type index, string const& str,
// size_type index_str, size_type count)
s.insert(8, " is an example string."s, 0, 14);
EXPECT_EQ("Exemplar is an example", s);

// insert(const_iterator pos, char ch)
s.insert(s.cbegin() + s.find_first_of('n') + 1, ':');
EXPECT_EQ("Exemplar is an: example", s);

// insert(const_iterator pos, size_type count, char ch)
s.insert(s.cbegin() + s.find_first_of(':') + 1, 2, '=');
EXPECT_EQ("Exemplar is an:== example", s);

// insert(const_iterator pos, InputIt first, InputIt last)
{
string_t seq = " string";
s.insert(s.cbegin() + s.find_last_of('e') + 1,
std::begin(seq), std::end(seq));
EXPECT_EQ("Exemplar is an:== example string", s);
}

// insert(const_iterator pos, std::initializer_list<char>)
s.insert(s.cbegin() + s.find_first_of('g') + 1, { '.' });
EXPECT_EQ("Exemplar is an:== example string.", s);
}

TEST(container_concept, container_concept_travis_bug)
{
container_concept_travis_bug_test<std::string>();

if constexpr(!detail::sequence_concept_modified_by_const_iterator_bug)
container_concept_const_travis_bug_test<std::string>();
}

TEST(container_concept, sequence_concept)
Expand All @@ -63,6 +204,12 @@ TEST(container_concept, sequence_concept)
EXPECT_TRUE((seqan3::sequence_concept<std::vector<char>>));
EXPECT_TRUE((seqan3::sequence_concept<std::deque<char>>));
EXPECT_TRUE((seqan3::sequence_concept<std::string>));
EXPECT_TRUE((seqan3::sequence_concept<seqan3::concatenated_sequences<std::vector<char>>>));

if constexpr(!detail::sequence_concept_modified_by_const_iterator_bug)
{
EXPECT_TRUE((seqan3::sequence_concept<seqan3::concatenated_sequences<std::string>>));
}
}

TEST(container_concept, random_access_sequence_concept)
Expand All @@ -73,6 +220,12 @@ TEST(container_concept, random_access_sequence_concept)
EXPECT_TRUE((seqan3::random_access_sequence_concept<std::vector<char>>));
EXPECT_TRUE((seqan3::random_access_sequence_concept<std::deque<char>>));
EXPECT_TRUE((seqan3::random_access_sequence_concept<std::string>));
EXPECT_TRUE((seqan3::random_access_sequence_concept<seqan3::concatenated_sequences<std::vector<char>>>));

if constexpr(!detail::sequence_concept_modified_by_const_iterator_bug)
{
EXPECT_TRUE((seqan3::random_access_sequence_concept<seqan3::concatenated_sequences<std::string>>));
}
}

TEST(container_concept, reservable_sequence_concept)
Expand All @@ -83,6 +236,12 @@ TEST(container_concept, reservable_sequence_concept)
EXPECT_TRUE((seqan3::reservable_sequence_concept<std::vector<char>>));
EXPECT_FALSE((seqan3::reservable_sequence_concept<std::deque<char>>));
EXPECT_TRUE((seqan3::reservable_sequence_concept<std::string>));
EXPECT_TRUE((seqan3::reservable_sequence_concept<seqan3::concatenated_sequences<std::vector<char>>>));

if constexpr(!detail::sequence_concept_modified_by_const_iterator_bug)
{
EXPECT_TRUE((seqan3::reservable_sequence_concept<seqan3::concatenated_sequences<std::string>>));
}
}

/* Check the SDSL containers */
Expand Down

0 comments on commit bafac27

Please sign in to comment.