Design iterator adaptor to convert between unrelated objects












0














I have the following MWE:



#include <iostream>
#include <vector>

using namespace std;

class LegacyWidgetData
{
private:
double _a;
double _b;

public:
LegacyWidgetData()
: _a(0), _b(0)
{}

LegacyWidgetData(const double &a, const double &b)
: _a(a), _b(b)
{}

LegacyWidgetData(const LegacyWidgetData& w)
: _a(w.a()), _b(w.b())
{}

inline double &a()
{
return _a;
}

inline double a() const
{
return _a;
}

inline double &b()
{
return _b;
}

inline double b() const
{
return _b;
}
};

template <std::size_t D>
class GenericWidgetData
{
private:
double data[D];

public:
GenericWidgetData(double a, double b)
{
data[0] = a;
data[1] = b;
}

GenericWidgetData(double a, double b, double c)
{
data[0] = a;
data[1] = b;
data[2] = c;
}

double get(int idx)
{
return data[idx];
}

void set(int idx, const double& v)
{
data[idx] = v;
}
};

template <typename Iterator>
void dummyFunction(Iterator begin, Iterator end)
{
for (auto it = begin; it != end; it++)
{
cout << "Before: " << it->a() << "," << it->b() << "t";
it->a() += 1;
it->b() -= 1;
cout << "After: " << it->a() << "," << it->b() << "n";
}
}

int main()
{
vector<LegacyWidgetData> c1{{1, 2}, {3, 4}, {5, 6}};
dummyFunction(c1.begin(), c1.end());

vector<GenericWidgetData<3>> c2{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

// dummyFunction(c2.begin(), c2.end()); // Will not compile
return 0;
}


I have the following assumptions/restrictions:




  1. I cannot modify the implementation of LegacyWidgetData or dummyFunction

  2. I can add methods to GenericWidgetData, and add any iterator adaptors as may be needed.


What I'd like to have is some sort of a iterator adaptor that when applied to any kind of iterator of GenericWidgetData gives me an iterator that acts like an iterator of LegacyWidgetData, without any caching/creation of intermediate object involved. Big props if this can be done in compile-time using template meta programming!










share|improve this question
























  • Why would you expect it to compile as dummyFunction use members functions a and bwhich does not exists in GenericWidgetData. It might help to read compiler error message!
    – Phil1970
    Nov 14 '18 at 1:42










  • @Phil1970 It might help if you read the question in its entirety
    – TCSGrad
    Nov 14 '18 at 1:55










  • Read your question again and tell me where is the question. The purpose of the site is not to write code for other peoples or do their homework.
    – Phil1970
    Nov 14 '18 at 2:40
















0














I have the following MWE:



#include <iostream>
#include <vector>

using namespace std;

class LegacyWidgetData
{
private:
double _a;
double _b;

public:
LegacyWidgetData()
: _a(0), _b(0)
{}

LegacyWidgetData(const double &a, const double &b)
: _a(a), _b(b)
{}

LegacyWidgetData(const LegacyWidgetData& w)
: _a(w.a()), _b(w.b())
{}

inline double &a()
{
return _a;
}

inline double a() const
{
return _a;
}

inline double &b()
{
return _b;
}

inline double b() const
{
return _b;
}
};

template <std::size_t D>
class GenericWidgetData
{
private:
double data[D];

public:
GenericWidgetData(double a, double b)
{
data[0] = a;
data[1] = b;
}

GenericWidgetData(double a, double b, double c)
{
data[0] = a;
data[1] = b;
data[2] = c;
}

double get(int idx)
{
return data[idx];
}

void set(int idx, const double& v)
{
data[idx] = v;
}
};

template <typename Iterator>
void dummyFunction(Iterator begin, Iterator end)
{
for (auto it = begin; it != end; it++)
{
cout << "Before: " << it->a() << "," << it->b() << "t";
it->a() += 1;
it->b() -= 1;
cout << "After: " << it->a() << "," << it->b() << "n";
}
}

int main()
{
vector<LegacyWidgetData> c1{{1, 2}, {3, 4}, {5, 6}};
dummyFunction(c1.begin(), c1.end());

vector<GenericWidgetData<3>> c2{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

// dummyFunction(c2.begin(), c2.end()); // Will not compile
return 0;
}


I have the following assumptions/restrictions:




  1. I cannot modify the implementation of LegacyWidgetData or dummyFunction

  2. I can add methods to GenericWidgetData, and add any iterator adaptors as may be needed.


What I'd like to have is some sort of a iterator adaptor that when applied to any kind of iterator of GenericWidgetData gives me an iterator that acts like an iterator of LegacyWidgetData, without any caching/creation of intermediate object involved. Big props if this can be done in compile-time using template meta programming!










share|improve this question
























  • Why would you expect it to compile as dummyFunction use members functions a and bwhich does not exists in GenericWidgetData. It might help to read compiler error message!
    – Phil1970
    Nov 14 '18 at 1:42










  • @Phil1970 It might help if you read the question in its entirety
    – TCSGrad
    Nov 14 '18 at 1:55










  • Read your question again and tell me where is the question. The purpose of the site is not to write code for other peoples or do their homework.
    – Phil1970
    Nov 14 '18 at 2:40














0












0








0







I have the following MWE:



#include <iostream>
#include <vector>

using namespace std;

class LegacyWidgetData
{
private:
double _a;
double _b;

public:
LegacyWidgetData()
: _a(0), _b(0)
{}

LegacyWidgetData(const double &a, const double &b)
: _a(a), _b(b)
{}

LegacyWidgetData(const LegacyWidgetData& w)
: _a(w.a()), _b(w.b())
{}

inline double &a()
{
return _a;
}

inline double a() const
{
return _a;
}

inline double &b()
{
return _b;
}

inline double b() const
{
return _b;
}
};

template <std::size_t D>
class GenericWidgetData
{
private:
double data[D];

public:
GenericWidgetData(double a, double b)
{
data[0] = a;
data[1] = b;
}

GenericWidgetData(double a, double b, double c)
{
data[0] = a;
data[1] = b;
data[2] = c;
}

double get(int idx)
{
return data[idx];
}

void set(int idx, const double& v)
{
data[idx] = v;
}
};

template <typename Iterator>
void dummyFunction(Iterator begin, Iterator end)
{
for (auto it = begin; it != end; it++)
{
cout << "Before: " << it->a() << "," << it->b() << "t";
it->a() += 1;
it->b() -= 1;
cout << "After: " << it->a() << "," << it->b() << "n";
}
}

int main()
{
vector<LegacyWidgetData> c1{{1, 2}, {3, 4}, {5, 6}};
dummyFunction(c1.begin(), c1.end());

vector<GenericWidgetData<3>> c2{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

// dummyFunction(c2.begin(), c2.end()); // Will not compile
return 0;
}


I have the following assumptions/restrictions:




  1. I cannot modify the implementation of LegacyWidgetData or dummyFunction

  2. I can add methods to GenericWidgetData, and add any iterator adaptors as may be needed.


What I'd like to have is some sort of a iterator adaptor that when applied to any kind of iterator of GenericWidgetData gives me an iterator that acts like an iterator of LegacyWidgetData, without any caching/creation of intermediate object involved. Big props if this can be done in compile-time using template meta programming!










share|improve this question















I have the following MWE:



#include <iostream>
#include <vector>

using namespace std;

class LegacyWidgetData
{
private:
double _a;
double _b;

public:
LegacyWidgetData()
: _a(0), _b(0)
{}

LegacyWidgetData(const double &a, const double &b)
: _a(a), _b(b)
{}

LegacyWidgetData(const LegacyWidgetData& w)
: _a(w.a()), _b(w.b())
{}

inline double &a()
{
return _a;
}

inline double a() const
{
return _a;
}

inline double &b()
{
return _b;
}

inline double b() const
{
return _b;
}
};

template <std::size_t D>
class GenericWidgetData
{
private:
double data[D];

public:
GenericWidgetData(double a, double b)
{
data[0] = a;
data[1] = b;
}

GenericWidgetData(double a, double b, double c)
{
data[0] = a;
data[1] = b;
data[2] = c;
}

double get(int idx)
{
return data[idx];
}

void set(int idx, const double& v)
{
data[idx] = v;
}
};

template <typename Iterator>
void dummyFunction(Iterator begin, Iterator end)
{
for (auto it = begin; it != end; it++)
{
cout << "Before: " << it->a() << "," << it->b() << "t";
it->a() += 1;
it->b() -= 1;
cout << "After: " << it->a() << "," << it->b() << "n";
}
}

int main()
{
vector<LegacyWidgetData> c1{{1, 2}, {3, 4}, {5, 6}};
dummyFunction(c1.begin(), c1.end());

vector<GenericWidgetData<3>> c2{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

// dummyFunction(c2.begin(), c2.end()); // Will not compile
return 0;
}


I have the following assumptions/restrictions:




  1. I cannot modify the implementation of LegacyWidgetData or dummyFunction

  2. I can add methods to GenericWidgetData, and add any iterator adaptors as may be needed.


What I'd like to have is some sort of a iterator adaptor that when applied to any kind of iterator of GenericWidgetData gives me an iterator that acts like an iterator of LegacyWidgetData, without any caching/creation of intermediate object involved. Big props if this can be done in compile-time using template meta programming!







templates iterator c++14 template-meta-programming






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 1:22









DeiDei

6,10053254




6,10053254










asked Nov 14 '18 at 0:54









TCSGrad

5,351104062




5,351104062












  • Why would you expect it to compile as dummyFunction use members functions a and bwhich does not exists in GenericWidgetData. It might help to read compiler error message!
    – Phil1970
    Nov 14 '18 at 1:42










  • @Phil1970 It might help if you read the question in its entirety
    – TCSGrad
    Nov 14 '18 at 1:55










  • Read your question again and tell me where is the question. The purpose of the site is not to write code for other peoples or do their homework.
    – Phil1970
    Nov 14 '18 at 2:40


















  • Why would you expect it to compile as dummyFunction use members functions a and bwhich does not exists in GenericWidgetData. It might help to read compiler error message!
    – Phil1970
    Nov 14 '18 at 1:42










  • @Phil1970 It might help if you read the question in its entirety
    – TCSGrad
    Nov 14 '18 at 1:55










  • Read your question again and tell me where is the question. The purpose of the site is not to write code for other peoples or do their homework.
    – Phil1970
    Nov 14 '18 at 2:40
















Why would you expect it to compile as dummyFunction use members functions a and bwhich does not exists in GenericWidgetData. It might help to read compiler error message!
– Phil1970
Nov 14 '18 at 1:42




Why would you expect it to compile as dummyFunction use members functions a and bwhich does not exists in GenericWidgetData. It might help to read compiler error message!
– Phil1970
Nov 14 '18 at 1:42












@Phil1970 It might help if you read the question in its entirety
– TCSGrad
Nov 14 '18 at 1:55




@Phil1970 It might help if you read the question in its entirety
– TCSGrad
Nov 14 '18 at 1:55












Read your question again and tell me where is the question. The purpose of the site is not to write code for other peoples or do their homework.
– Phil1970
Nov 14 '18 at 2:40




Read your question again and tell me where is the question. The purpose of the site is not to write code for other peoples or do their homework.
– Phil1970
Nov 14 '18 at 2:40












2 Answers
2






active

oldest

votes


















1














What you could do is add a template specialization to GenericWidgetData for when D == 2 and then implement the .a() and .b() functions to match LegacyWidgetData's interface.



Even if an iterator adapter that could switch at compile-time with some metaprogramming tricks could be written, it would be very complicated to be understood by anyone but its own writer.






share|improve this answer























  • You overlooked the restraint that I cannot edit dummyFunction (which is just one of a thousand different functions that accept iterators of LegacyWidgetData) - without that restraint, the problem becomes much simpler.
    – TCSGrad
    Nov 14 '18 at 1:25






  • 1




    @TCSGrad Ah, apologies. Well, you're in quite a pickle then. You could probably add a templare specialization to GenericWidget for D == 2 that includes member functions .a() and .b() to comply with LegacyWidget's interface.
    – DeiDei
    Nov 14 '18 at 1:28










  • That actually makes sense for this toy example, but not for my actual code base (which basically wraps the iterator in a another class which has some custom properties) - seems I have to distill the problem into a better example without simplifying it too much! If you can edit you answer to reflect your comment, I'll accept it and work on a better MWE for a different question.
    – TCSGrad
    Nov 14 '18 at 1:32





















-1














If you have iterator adaptor, then you would typically need two such objects.



And if you have a lot of those algorithms, then it would make sense to hide the vector inside another class whose begin/end method would returns adaptors instead. Something more or less like that:



templace <std::size_t D> class MyContainer
{
public:
MyAdaptor<D> begin();
MyAdaptor<D> end();
private:
std::vector<GenericWidgetData<D>> data;
};


However, it might make sense to simply add the appropriate functions to GenericWidgetData. In that case, you might want to have some specializations so that for example b() is only available if size is 2 or more etc.



Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function.



double& b(LegacyWidgetData &data) { return data.b(); }
const double& b(const LegacyWidgetData &data) { return data.b(); }


And you would then add overloads for GenericWidgetData as appropriate. Using static_assertfor validation might work relatively well in that case:



template <std::size_t D> double& b(GenericWidgetData<D> &widgetData)
{
static_assert(D > 1, "b is available only if D is big enough");
return widgetData.data[D]; // Or an accessor function to avoid making it public
}


You would then add the const variation too.



It is more works but it is more flexible. For example, you can have proper validation of the dimension per function.



Alternatively, another solution is to have extra parameters to your algorithm for the transformation to apply.



template <typename Iterator, typename FA, typename FB>
void dummyFunction(Iterator begin, Iterator end, FA fa, FB fb)
{
for (auto it = begin; it != end; it++)
{
cout << "Before: " << fa(*it) << "," << fb(*it) << "t";
fa(*it) += 1;
fa(*it) -= 1;
cout << "After: " << fa(*it) << "," << fb(*it) << "n";
}
}


This might seems a lot of work but then you are very flexible. So maybe, you can reconsider which code you want to modify.



It might be better to make such change now and have cleaner code in the future than to create an adaptor or add many functions to GenericWidgetData that are intended to be used only by the algorithms.






share|improve this answer





















  • "Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function." I take it you've never worked in a code base in which certain parts are read-only ?
    – TCSGrad
    Nov 14 '18 at 16:04










  • If your software company wrote the code and the code is not adequate anymore, then improve it. If you use a lot your library of 1000 functions, then making them easier to use would pay by itself in simplicity of writing new code and reduced maintenance. Unit testing is a good way to ensure you don't introduce new bugs in your code but given that your change are trivial, maybe you could make a copy of the code and change it. With find and replace you might be able to update the library in a day or 2.
    – Phil1970
    Nov 15 '18 at 5:43













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53291653%2fdesign-iterator-adaptor-to-convert-between-unrelated-objects%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














What you could do is add a template specialization to GenericWidgetData for when D == 2 and then implement the .a() and .b() functions to match LegacyWidgetData's interface.



Even if an iterator adapter that could switch at compile-time with some metaprogramming tricks could be written, it would be very complicated to be understood by anyone but its own writer.






share|improve this answer























  • You overlooked the restraint that I cannot edit dummyFunction (which is just one of a thousand different functions that accept iterators of LegacyWidgetData) - without that restraint, the problem becomes much simpler.
    – TCSGrad
    Nov 14 '18 at 1:25






  • 1




    @TCSGrad Ah, apologies. Well, you're in quite a pickle then. You could probably add a templare specialization to GenericWidget for D == 2 that includes member functions .a() and .b() to comply with LegacyWidget's interface.
    – DeiDei
    Nov 14 '18 at 1:28










  • That actually makes sense for this toy example, but not for my actual code base (which basically wraps the iterator in a another class which has some custom properties) - seems I have to distill the problem into a better example without simplifying it too much! If you can edit you answer to reflect your comment, I'll accept it and work on a better MWE for a different question.
    – TCSGrad
    Nov 14 '18 at 1:32


















1














What you could do is add a template specialization to GenericWidgetData for when D == 2 and then implement the .a() and .b() functions to match LegacyWidgetData's interface.



Even if an iterator adapter that could switch at compile-time with some metaprogramming tricks could be written, it would be very complicated to be understood by anyone but its own writer.






share|improve this answer























  • You overlooked the restraint that I cannot edit dummyFunction (which is just one of a thousand different functions that accept iterators of LegacyWidgetData) - without that restraint, the problem becomes much simpler.
    – TCSGrad
    Nov 14 '18 at 1:25






  • 1




    @TCSGrad Ah, apologies. Well, you're in quite a pickle then. You could probably add a templare specialization to GenericWidget for D == 2 that includes member functions .a() and .b() to comply with LegacyWidget's interface.
    – DeiDei
    Nov 14 '18 at 1:28










  • That actually makes sense for this toy example, but not for my actual code base (which basically wraps the iterator in a another class which has some custom properties) - seems I have to distill the problem into a better example without simplifying it too much! If you can edit you answer to reflect your comment, I'll accept it and work on a better MWE for a different question.
    – TCSGrad
    Nov 14 '18 at 1:32
















1












1








1






What you could do is add a template specialization to GenericWidgetData for when D == 2 and then implement the .a() and .b() functions to match LegacyWidgetData's interface.



Even if an iterator adapter that could switch at compile-time with some metaprogramming tricks could be written, it would be very complicated to be understood by anyone but its own writer.






share|improve this answer














What you could do is add a template specialization to GenericWidgetData for when D == 2 and then implement the .a() and .b() functions to match LegacyWidgetData's interface.



Even if an iterator adapter that could switch at compile-time with some metaprogramming tricks could be written, it would be very complicated to be understood by anyone but its own writer.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 14 '18 at 1:38

























answered Nov 14 '18 at 1:21









DeiDei

6,10053254




6,10053254












  • You overlooked the restraint that I cannot edit dummyFunction (which is just one of a thousand different functions that accept iterators of LegacyWidgetData) - without that restraint, the problem becomes much simpler.
    – TCSGrad
    Nov 14 '18 at 1:25






  • 1




    @TCSGrad Ah, apologies. Well, you're in quite a pickle then. You could probably add a templare specialization to GenericWidget for D == 2 that includes member functions .a() and .b() to comply with LegacyWidget's interface.
    – DeiDei
    Nov 14 '18 at 1:28










  • That actually makes sense for this toy example, but not for my actual code base (which basically wraps the iterator in a another class which has some custom properties) - seems I have to distill the problem into a better example without simplifying it too much! If you can edit you answer to reflect your comment, I'll accept it and work on a better MWE for a different question.
    – TCSGrad
    Nov 14 '18 at 1:32




















  • You overlooked the restraint that I cannot edit dummyFunction (which is just one of a thousand different functions that accept iterators of LegacyWidgetData) - without that restraint, the problem becomes much simpler.
    – TCSGrad
    Nov 14 '18 at 1:25






  • 1




    @TCSGrad Ah, apologies. Well, you're in quite a pickle then. You could probably add a templare specialization to GenericWidget for D == 2 that includes member functions .a() and .b() to comply with LegacyWidget's interface.
    – DeiDei
    Nov 14 '18 at 1:28










  • That actually makes sense for this toy example, but not for my actual code base (which basically wraps the iterator in a another class which has some custom properties) - seems I have to distill the problem into a better example without simplifying it too much! If you can edit you answer to reflect your comment, I'll accept it and work on a better MWE for a different question.
    – TCSGrad
    Nov 14 '18 at 1:32


















You overlooked the restraint that I cannot edit dummyFunction (which is just one of a thousand different functions that accept iterators of LegacyWidgetData) - without that restraint, the problem becomes much simpler.
– TCSGrad
Nov 14 '18 at 1:25




You overlooked the restraint that I cannot edit dummyFunction (which is just one of a thousand different functions that accept iterators of LegacyWidgetData) - without that restraint, the problem becomes much simpler.
– TCSGrad
Nov 14 '18 at 1:25




1




1




@TCSGrad Ah, apologies. Well, you're in quite a pickle then. You could probably add a templare specialization to GenericWidget for D == 2 that includes member functions .a() and .b() to comply with LegacyWidget's interface.
– DeiDei
Nov 14 '18 at 1:28




@TCSGrad Ah, apologies. Well, you're in quite a pickle then. You could probably add a templare specialization to GenericWidget for D == 2 that includes member functions .a() and .b() to comply with LegacyWidget's interface.
– DeiDei
Nov 14 '18 at 1:28












That actually makes sense for this toy example, but not for my actual code base (which basically wraps the iterator in a another class which has some custom properties) - seems I have to distill the problem into a better example without simplifying it too much! If you can edit you answer to reflect your comment, I'll accept it and work on a better MWE for a different question.
– TCSGrad
Nov 14 '18 at 1:32






That actually makes sense for this toy example, but not for my actual code base (which basically wraps the iterator in a another class which has some custom properties) - seems I have to distill the problem into a better example without simplifying it too much! If you can edit you answer to reflect your comment, I'll accept it and work on a better MWE for a different question.
– TCSGrad
Nov 14 '18 at 1:32















-1














If you have iterator adaptor, then you would typically need two such objects.



And if you have a lot of those algorithms, then it would make sense to hide the vector inside another class whose begin/end method would returns adaptors instead. Something more or less like that:



templace <std::size_t D> class MyContainer
{
public:
MyAdaptor<D> begin();
MyAdaptor<D> end();
private:
std::vector<GenericWidgetData<D>> data;
};


However, it might make sense to simply add the appropriate functions to GenericWidgetData. In that case, you might want to have some specializations so that for example b() is only available if size is 2 or more etc.



Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function.



double& b(LegacyWidgetData &data) { return data.b(); }
const double& b(const LegacyWidgetData &data) { return data.b(); }


And you would then add overloads for GenericWidgetData as appropriate. Using static_assertfor validation might work relatively well in that case:



template <std::size_t D> double& b(GenericWidgetData<D> &widgetData)
{
static_assert(D > 1, "b is available only if D is big enough");
return widgetData.data[D]; // Or an accessor function to avoid making it public
}


You would then add the const variation too.



It is more works but it is more flexible. For example, you can have proper validation of the dimension per function.



Alternatively, another solution is to have extra parameters to your algorithm for the transformation to apply.



template <typename Iterator, typename FA, typename FB>
void dummyFunction(Iterator begin, Iterator end, FA fa, FB fb)
{
for (auto it = begin; it != end; it++)
{
cout << "Before: " << fa(*it) << "," << fb(*it) << "t";
fa(*it) += 1;
fa(*it) -= 1;
cout << "After: " << fa(*it) << "," << fb(*it) << "n";
}
}


This might seems a lot of work but then you are very flexible. So maybe, you can reconsider which code you want to modify.



It might be better to make such change now and have cleaner code in the future than to create an adaptor or add many functions to GenericWidgetData that are intended to be used only by the algorithms.






share|improve this answer





















  • "Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function." I take it you've never worked in a code base in which certain parts are read-only ?
    – TCSGrad
    Nov 14 '18 at 16:04










  • If your software company wrote the code and the code is not adequate anymore, then improve it. If you use a lot your library of 1000 functions, then making them easier to use would pay by itself in simplicity of writing new code and reduced maintenance. Unit testing is a good way to ensure you don't introduce new bugs in your code but given that your change are trivial, maybe you could make a copy of the code and change it. With find and replace you might be able to update the library in a day or 2.
    – Phil1970
    Nov 15 '18 at 5:43


















-1














If you have iterator adaptor, then you would typically need two such objects.



And if you have a lot of those algorithms, then it would make sense to hide the vector inside another class whose begin/end method would returns adaptors instead. Something more or less like that:



templace <std::size_t D> class MyContainer
{
public:
MyAdaptor<D> begin();
MyAdaptor<D> end();
private:
std::vector<GenericWidgetData<D>> data;
};


However, it might make sense to simply add the appropriate functions to GenericWidgetData. In that case, you might want to have some specializations so that for example b() is only available if size is 2 or more etc.



Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function.



double& b(LegacyWidgetData &data) { return data.b(); }
const double& b(const LegacyWidgetData &data) { return data.b(); }


And you would then add overloads for GenericWidgetData as appropriate. Using static_assertfor validation might work relatively well in that case:



template <std::size_t D> double& b(GenericWidgetData<D> &widgetData)
{
static_assert(D > 1, "b is available only if D is big enough");
return widgetData.data[D]; // Or an accessor function to avoid making it public
}


You would then add the const variation too.



It is more works but it is more flexible. For example, you can have proper validation of the dimension per function.



Alternatively, another solution is to have extra parameters to your algorithm for the transformation to apply.



template <typename Iterator, typename FA, typename FB>
void dummyFunction(Iterator begin, Iterator end, FA fa, FB fb)
{
for (auto it = begin; it != end; it++)
{
cout << "Before: " << fa(*it) << "," << fb(*it) << "t";
fa(*it) += 1;
fa(*it) -= 1;
cout << "After: " << fa(*it) << "," << fb(*it) << "n";
}
}


This might seems a lot of work but then you are very flexible. So maybe, you can reconsider which code you want to modify.



It might be better to make such change now and have cleaner code in the future than to create an adaptor or add many functions to GenericWidgetData that are intended to be used only by the algorithms.






share|improve this answer





















  • "Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function." I take it you've never worked in a code base in which certain parts are read-only ?
    – TCSGrad
    Nov 14 '18 at 16:04










  • If your software company wrote the code and the code is not adequate anymore, then improve it. If you use a lot your library of 1000 functions, then making them easier to use would pay by itself in simplicity of writing new code and reduced maintenance. Unit testing is a good way to ensure you don't introduce new bugs in your code but given that your change are trivial, maybe you could make a copy of the code and change it. With find and replace you might be able to update the library in a day or 2.
    – Phil1970
    Nov 15 '18 at 5:43
















-1












-1








-1






If you have iterator adaptor, then you would typically need two such objects.



And if you have a lot of those algorithms, then it would make sense to hide the vector inside another class whose begin/end method would returns adaptors instead. Something more or less like that:



templace <std::size_t D> class MyContainer
{
public:
MyAdaptor<D> begin();
MyAdaptor<D> end();
private:
std::vector<GenericWidgetData<D>> data;
};


However, it might make sense to simply add the appropriate functions to GenericWidgetData. In that case, you might want to have some specializations so that for example b() is only available if size is 2 or more etc.



Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function.



double& b(LegacyWidgetData &data) { return data.b(); }
const double& b(const LegacyWidgetData &data) { return data.b(); }


And you would then add overloads for GenericWidgetData as appropriate. Using static_assertfor validation might work relatively well in that case:



template <std::size_t D> double& b(GenericWidgetData<D> &widgetData)
{
static_assert(D > 1, "b is available only if D is big enough");
return widgetData.data[D]; // Or an accessor function to avoid making it public
}


You would then add the const variation too.



It is more works but it is more flexible. For example, you can have proper validation of the dimension per function.



Alternatively, another solution is to have extra parameters to your algorithm for the transformation to apply.



template <typename Iterator, typename FA, typename FB>
void dummyFunction(Iterator begin, Iterator end, FA fa, FB fb)
{
for (auto it = begin; it != end; it++)
{
cout << "Before: " << fa(*it) << "," << fb(*it) << "t";
fa(*it) += 1;
fa(*it) -= 1;
cout << "After: " << fa(*it) << "," << fb(*it) << "n";
}
}


This might seems a lot of work but then you are very flexible. So maybe, you can reconsider which code you want to modify.



It might be better to make such change now and have cleaner code in the future than to create an adaptor or add many functions to GenericWidgetData that are intended to be used only by the algorithms.






share|improve this answer












If you have iterator adaptor, then you would typically need two such objects.



And if you have a lot of those algorithms, then it would make sense to hide the vector inside another class whose begin/end method would returns adaptors instead. Something more or less like that:



templace <std::size_t D> class MyContainer
{
public:
MyAdaptor<D> begin();
MyAdaptor<D> end();
private:
std::vector<GenericWidgetData<D>> data;
};


However, it might make sense to simply add the appropriate functions to GenericWidgetData. In that case, you might want to have some specializations so that for example b() is only available if size is 2 or more etc.



Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function.



double& b(LegacyWidgetData &data) { return data.b(); }
const double& b(const LegacyWidgetData &data) { return data.b(); }


And you would then add overloads for GenericWidgetData as appropriate. Using static_assertfor validation might work relatively well in that case:



template <std::size_t D> double& b(GenericWidgetData<D> &widgetData)
{
static_assert(D > 1, "b is available only if D is big enough");
return widgetData.data[D]; // Or an accessor function to avoid making it public
}


You would then add the const variation too.



It is more works but it is more flexible. For example, you can have proper validation of the dimension per function.



Alternatively, another solution is to have extra parameters to your algorithm for the transformation to apply.



template <typename Iterator, typename FA, typename FB>
void dummyFunction(Iterator begin, Iterator end, FA fa, FB fb)
{
for (auto it = begin; it != end; it++)
{
cout << "Before: " << fa(*it) << "," << fb(*it) << "t";
fa(*it) += 1;
fa(*it) -= 1;
cout << "After: " << fa(*it) << "," << fb(*it) << "n";
}
}


This might seems a lot of work but then you are very flexible. So maybe, you can reconsider which code you want to modify.



It might be better to make such change now and have cleaner code in the future than to create an adaptor or add many functions to GenericWidgetData that are intended to be used only by the algorithms.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 14 '18 at 2:24









Phil1970

1,111189




1,111189












  • "Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function." I take it you've never worked in a code base in which certain parts are read-only ?
    – TCSGrad
    Nov 14 '18 at 16:04










  • If your software company wrote the code and the code is not adequate anymore, then improve it. If you use a lot your library of 1000 functions, then making them easier to use would pay by itself in simplicity of writing new code and reduced maintenance. Unit testing is a good way to ensure you don't introduce new bugs in your code but given that your change are trivial, maybe you could make a copy of the code and change it. With find and replace you might be able to update the library in a day or 2.
    – Phil1970
    Nov 15 '18 at 5:43




















  • "Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function." I take it you've never worked in a code base in which certain parts are read-only ?
    – TCSGrad
    Nov 14 '18 at 16:04










  • If your software company wrote the code and the code is not adequate anymore, then improve it. If you use a lot your library of 1000 functions, then making them easier to use would pay by itself in simplicity of writing new code and reduced maintenance. Unit testing is a good way to ensure you don't introduce new bugs in your code but given that your change are trivial, maybe you could make a copy of the code and change it. With find and replace you might be able to update the library in a day or 2.
    – Phil1970
    Nov 15 '18 at 5:43


















"Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function." I take it you've never worked in a code base in which certain parts are read-only ?
– TCSGrad
Nov 14 '18 at 16:04




"Neverthless, the best solution would probably be to modify the 1000 functions so that instead of accessing directly members of LegacyWidgetData, then would call a free function." I take it you've never worked in a code base in which certain parts are read-only ?
– TCSGrad
Nov 14 '18 at 16:04












If your software company wrote the code and the code is not adequate anymore, then improve it. If you use a lot your library of 1000 functions, then making them easier to use would pay by itself in simplicity of writing new code and reduced maintenance. Unit testing is a good way to ensure you don't introduce new bugs in your code but given that your change are trivial, maybe you could make a copy of the code and change it. With find and replace you might be able to update the library in a day or 2.
– Phil1970
Nov 15 '18 at 5:43






If your software company wrote the code and the code is not adequate anymore, then improve it. If you use a lot your library of 1000 functions, then making them easier to use would pay by itself in simplicity of writing new code and reduced maintenance. Unit testing is a good way to ensure you don't introduce new bugs in your code but given that your change are trivial, maybe you could make a copy of the code and change it. With find and replace you might be able to update the library in a day or 2.
– Phil1970
Nov 15 '18 at 5:43




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53291653%2fdesign-iterator-adaptor-to-convert-between-unrelated-objects%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Guess what letter conforming each word

Port of Spain

Run scheduled task as local user group (not BUILTIN)