Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds stringTo and stringFrom conversion functions #542

Closed
wants to merge 29 commits into from

Conversation

cugone
Copy link
Contributor

@cugone cugone commented Mar 21, 2020

No description provided.

@cugone cugone requested a review from DanRStevens March 21, 2020 02:36
@cugone
Copy link
Contributor Author

cugone commented Mar 21, 2020

@DanRStevens You have easier access to Linux in order to figure out what they want in terms of extern template functions. It's been a feature since c++11 so I don't understand why Linux, GCC, GCC-8, MinGW, and MacOS all give different errors.

Allow the compiler to promote values to the larger type for comparison.
Literals will be either `int` or `double`, so will often be the larger
type.
src/StringUtils.cpp Outdated Show resolved Hide resolved
Copy link
Collaborator

@DanRStevens DanRStevens left a comment

Choose a reason for hiding this comment

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

It may be possible to greatly reduce the bulk of the test code. The tests cases are highly symmetric for similar types of different sizes. We can potentially use Typed Tests to reduce the repetition.

src/StringUtils.cpp Outdated Show resolved Hide resolved
src/StringUtils.cpp Outdated Show resolved Hide resolved
test/StringUtils.test.cpp Outdated Show resolved Hide resolved
test/StringUtils.test.cpp Outdated Show resolved Hide resolved
cugone added 4 commits March 22, 2020 19:42
Requires the explicit instantiation declarations to be in the header or the linker gets confused.
More code, for less copy-paste errors.
Copy link
Collaborator

@DanRStevens DanRStevens left a comment

Choose a reason for hiding this comment

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

In regards to char literals, I suggest using char literal syntax.

test/StringUtils.test.cpp Outdated Show resolved Hide resolved
test/StringUtils.test.cpp Outdated Show resolved Hide resolved
test/StringUtils.test.cpp Outdated Show resolved Hide resolved
test/StringUtils.test.cpp Outdated Show resolved Hide resolved
test/StringUtils.test.cpp Outdated Show resolved Hide resolved
test/StringUtils.test.cpp Outdated Show resolved Hide resolved
test/StringUtils.test.cpp Outdated Show resolved Hide resolved
@DanRStevens
Copy link
Collaborator

The current failures look familiar. I think it was a bug in Google Test. Can't remember where I saw it before though.

@cugone
Copy link
Contributor Author

cugone commented Mar 23, 2020

Linux is failing to compile because of -Wgnu-zero-variadic-macro-arguments temporarily disabling or turning the warning off will get rid of the failure.

@DanRStevens
Copy link
Collaborator

The Google Test project has an open issue for this bug:
google/googletest#2271

Looks like the Docker image we are using for the Clang build has an up-to-date version of Google Test.

@cugone
Copy link
Contributor Author

cugone commented Mar 23, 2020

The advice given in the open issue and the several linked comments and prior issues is: "disable the warning when it provides no value"; "we don't support every warning"; "why are you trying to compile with -Wall and -Wextra?"...Gee, it's almost as if they don't want to fix it.

@cugone cugone force-pushed the stringConversion branch from caa8627 to 3635a8a Compare March 23, 2020 04:39
This is due to a bug in Google Test that is causing non-Windows builds to fail.
@cugone cugone force-pushed the stringConversion branch from 3635a8a to fc0ca0e Compare March 23, 2020 04:54
@DanRStevens
Copy link
Collaborator

Yeah, that comment was a little disappointing. Especially given how common -Wall and -Wextra are.


I found some stuff relevant to the extern template attempt:
What's the right way to specialize a template when using “extern template”?

It seems specializations must be known up front, before the template is used. That kind of makes sense, since if the compiler doesn't know about the specialization, it would try to use the generic version with appropriate substituted types. I'm a little surprised the linking doesn't work a bit differently for extern specializations, though I suppose the compiler is always free to inline functions if it wants to, and knowing about specializations will affect inlining.

It seems for free standing functions we don't need the extern keyword. Apparently it's mostly useful when you have class member functions that you want to make extern.

@cugone cugone force-pushed the stringConversion branch from 8c1c9c7 to a617a6b Compare March 23, 2020 07:29
@cugone cugone requested a review from DanRStevens March 23, 2020 07:41
Copy link
Collaborator

@DanRStevens DanRStevens left a comment

Choose a reason for hiding this comment

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

Well, I'm impressed with how far this has come.


We probably need to trim the test names a bit. I'm see a lot of line overflow in the terminal.

There's probably more we can do to reduce the bulkiness of the test code. Perhaps using Type Parameterized Tests for the round trip tests. Or maybe Value Parameterized tests. I'm not too sure about this yet.

src/StringUtils.cpp Outdated Show resolved Hide resolved
cugone added 2 commits March 23, 2020 08:42
It wasn't that special; also, provided more accurate error message
Copy link
Collaborator

@DanRStevens DanRStevens left a comment

Choose a reason for hiding this comment

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

I think we still need to split out the change that removes the NAS2D:: prefix and wraps everything in a namespace block. That change makes the results quite noisy, and hard to verify the PR as a whole.


The remaining code probably needs a bit of squashing.


For the test name, I've noticed only the Filesystem tests end in "Test". Maybe we should consider stripping that. That might be one way to shorten names, while avoiding abbreviations. Some names seem a bit too abbreviated now. Perhaps we can use "SignedInt" or "UnsignedInt". I don't mind too much if "Int" is used as an abbreviation, as that one is common and built into the language. Or maybe a different phrasing could be used.

Comment on lines +134 to +137
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can probably reduce the scope of this block. I think it might only need to wrap the use of TYPED_TEST_SUITE.

We can potentially combine the code for multiple types into one region. Looks like they can all be declared up front too. Maybe we should set a generic type alias at the head of the file for SignedTypes and UnsignedTypes, and then use the macro up near the top. The test methods can be below. It looks like that ordering is already used, so it should work.

Comment on lines +48 to +51
auto v = toLowercase(value);
if(v == "true") return true;
if(v == "false") return false;
throw std::invalid_argument("Value is not 'true' or 'false' value: " + value);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would prefer not using a highly abbreviated name such as v.


For that matter, I would prefer not including the toLowercase as part of this method. It takes choice away from the caller on how strict they want to be. Instead, let the caller decide if they should call toLowercase themselves.

This solves the above problem, since the value parameter can then be used throughout. There is no need for a secondary modified variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Normalizing strings is standard practice when comparing them; otherwise you'd have to write:

if(value == "true" || value == "TRUE" || value == "True" || value == "tRue" || value == "trUe" || value == "truE") return true;
//...etc

In this particular case, taking the argument by value to let the compiler generate a copy is probably better.

Copy link
Collaborator

Choose a reason for hiding this comment

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

In this case it would be stringTo<bool>(toLowercase(value)). That's easy enough to deal with. It also doesn't take away my choice if I want a case sensitive compare, in which case I can write stringTo<bool>(value).

By trying to be too clever and doing too much, we actually limit expressability and composability.


If we get rid of the toLowercase, the string use becomes entirely read-only. That removes the potential for move semantic optimizations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants