Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- // using std::find
- #include <initializer_list>
- // using std::initializer_list
- #include <cstdarg>
- // using std::va_list, va_start, va_end
- /* Some dummy code for use in the examples */
- struct Foo
- {
- int x;
- bool operator==(const Foo& o) const
- { return x == o.x; }
- };
- void bar(const Foo&);
- /* Code smell no 1: Multiple copy-and-paste function calls */
- void original_1()
- {
- Foo a, b, c;
- bar(a);
- bar(b);
- bar(c);
- }
- /* Solution: Use a range-based loop with an initializer_list */
- void refactored_1()
- {
- Foo a, b, c;
- for(const Foo* i: {&a, &b, &c})
- bar(*i);
- }
- /* Code smell no 2: variable argument lists in the 21st century
- *
- * Before anyone complains; yes there are still valid reasons for using them,
- * however, here we have better alternatives
- */
- Foo original_2(Foo searched, Foo def, int n, ...)
- {
- std::va_list ap;
- va_start(ap, n);
- for(int i = 0; i < n; ++i) {
- Foo cur = va_arg(ap, Foo);
- if(cur == searched) {
- va_end(ap);
- return cur;
- }
- }
- va_end(ap);
- return def;
- }
- /* Solution: initializer_list for arguments
- *
- * Obviously, this only works because we expect just a single type.
- * Replacing printf-style functions is still a challenge
- */
- Foo refactored_2(Foo searched, Foo def, const std::initializer_list<Foo>& lst)
- {
- std::initializer_list<Foo>::iterator found =
- std::find(lst.begin(), lst.end(), searched);
- return found == lst.end() ? def : *found;
- }
- /* Alternative solution: Pass iterators
- *
- * This is arguably more idiomatic, universal, and also works with obsolete
- * compilers.
- * On the other hand, it requires at least one more line of code to call it.
- * It still profits from initializer_lists, as demonstrated below
- */
- template<class Iterator>
- Foo alternative_2(Foo searched, Foo def, Iterator first, Iterator last)
- {
- Iterator found = std::find(first, last, searched);
- return found == last ? def : *found;
- }
- /* Demonstrates the usage of the various solutions for smell no. 2 */
- void call_2()
- {
- Foo a, b, c, d, e;
- Foo f = original_2(a, b, 3, c, d, e);
- Foo g = refactored_2(a, b, {c, d, e});
- const auto& lst = {c, d, e};
- Foo h = alternative_2(a, b, lst.begin(), lst.end());
- /* for completeness: alternative_2 with C++03 */
- const Foo arr[] = {c, d, e};
- Foo i = alternative_2(a, b, arr, arr + sizeof(arr)/ sizeof(*arr));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement