Skip to content

Commit

Permalink
fixed #48 (using nonmember begin/end)
Browse files Browse the repository at this point in the history
  • Loading branch information
nlohmann committed Mar 22, 2015
1 parent 5526de1 commit abc6137
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 6 deletions.
9 changes: 5 additions & 4 deletions src/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ class basic_json
{
Allocator<object_t> alloc;
m_value.object = alloc.allocate(1);
alloc.construct(m_value.object, value.begin(), value.end());
alloc.construct(m_value.object, std::begin(value), std::end(value));
}

/// create an array (explicit)
Expand Down Expand Up @@ -438,7 +438,7 @@ class basic_json
{
Allocator<array_t> alloc;
m_value.array = alloc.allocate(1);
alloc.construct(m_value.array, value.begin(), value.end());
alloc.construct(m_value.array, std::begin(value), std::end(value));
}

/// create a string (explicit)
Expand Down Expand Up @@ -3067,7 +3067,8 @@ class basic_json
@see <http://en.wikipedia.org/wiki/UTF-8#Sample_code>
*/
inline static string_t to_unicode(const size_t codepoint1, const size_t codepoint2 = 0)
inline static string_t to_unicode(const size_t codepoint1,
const size_t codepoint2 = 0)
{
string_t result;

Expand Down Expand Up @@ -3095,7 +3096,7 @@ class basic_json

if (codepoint <= 0x7f)
{
// 1-byte characters: 0xxxxxxx (ASCI)
// 1-byte characters: 0xxxxxxx (ASCII)
result.append(1, static_cast<typename string_t::value_type>(codepoint));
}
else if (codepoint <= 0x7ff)
Expand Down
4 changes: 2 additions & 2 deletions src/json.hpp.re2c
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ class basic_json
{
Allocator<object_t> alloc;
m_value.object = alloc.allocate(1);
alloc.construct(m_value.object, value.begin(), value.end());
alloc.construct(m_value.object, std::begin(value), std::end(value));
}

/// create an array (explicit)
Expand Down Expand Up @@ -438,7 +438,7 @@ class basic_json
{
Allocator<array_t> alloc;
m_value.array = alloc.allocate(1);
alloc.construct(m_value.array, value.begin(), value.end());
alloc.construct(m_value.array, std::begin(value), std::end(value));
}

/// create a string (explicit)
Expand Down

5 comments on commit abc6137

@gnzlbg
Copy link

@gnzlbg gnzlbg commented on abc6137 Mar 22, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That will just call the begin and end functions in the std namespace, but won't use those in the namespace of the corresponding type. For enabling ADL to kick in, the right way to do it is:

using std::begin;
using std::end;
// use unqualified begin(...), end(...)

C++ sucks :D

@nlohmann
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comment. But isn't std::begin(foo) just a function that returns foo.begin() for any type of foo?

@gnzlbg
Copy link

@gnzlbg gnzlbg commented on abc6137 Mar 24, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In standarese std::swap, std::begin, std::end, std::iter_swap, ... are customization points. They are defined in the std namespace and overloaded for some standard types, but when used as:

using std::swap;
swap(a, b); // this might call std::swap or some other swap!

argument dependent look-up is going to try and find a swap function declared in the namespace where the types of a and b are defined. Iff it doesn't find any, is going to try any swap function in scope (e.g. std::swap which is brought into scope by the using directive).

That is:

std::swap(a, b); // will always call std::swap!

doesn't do the same thing as using std::swap + unqualified call to swap.

But isn't std::begin(foo) just a function that returns foo.begin() for any type of foo?

std::begin is a free function, that can be overloaded for other types. It is, in particular, overloaded for C-Arrays, which don't have member functions. Since you don't have to modify the type to implement non-member non-friend begin for a type, it allows you to adapt e.g. third-party code (that you cannot modify) such that it can e.g. be used with the range-for statement.

@nlohmann
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I just do not know any user-defined types with iterators where std::begin would not do the job. But I understand your explanation and trust you that there is demand :-)

I'll update the code in a minute.

@gnzlbg
Copy link

@gnzlbg gnzlbg commented on abc6137 Mar 24, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use this on e.g. Eigen3 vectors and matrices which do not provide begin and end.

Please sign in to comment.