/* This doc is to investigate the issue brought by reference return type of a
* functor argument std::function. We expect it can pass the bypass function
* defined in top layer to less-context bottom layer and still work as designed.
* However we see weird behavior when it is std::function<const std::string&(int)>.
* Instead, std::function<const string*(int)> works fine...
*/
#include <iostream>
#include <vector>
#include <unordered_map>
#include <string>
#include <functional>
using namespace std;
// This class stores vectror of numbers and divisors. API getRemainderRing picks
// those numbers' remainder equal to given number after division. Bypass function
// is passed in as argument to print the names.
class Elements {
public:
Elements() = default;
Elements(int32_t maxNum, int32_t divisor) : _div(divisor) {
_data.clear();
_data.reserve(maxNum);
for (int32_t i = 0; i < maxNum; i++) {
_data.push_back(i);
}
}
void getRemainderRing(int32_t rmd, const std::function<const string&(int32_t)>& getName, string* output) {
output->clear();
for (int32_t i : _data) {
if (i % _div == rmd) {
// crashes here. getName(i) pointing to address 0
*output += getName(i) + " ";
}
}
}
private:
vector<int32_t> _data;
int32_t _div;
};
int main () {
unordered_map<int32_t, string> numToStr;
numToStr[0] = "null";
numToStr[1] = "eins";
numToStr[2] = "zwei";
numToStr[3] = "drei";
numToStr[4] = "vier";
// The functor
std::function<const string&(int32_t)> getName = [&numToStr](int32_t i) -> const string& { return numToStr[i]; };
Elements smallRing(4, 2); // contains {0,1,2,3}, divisor: 2
string result;
// This is actually to get all odd numbers < 4
smallRing.getRemainderRing(1, getName, &result);
// BOOM!
cout << result << endl;
return 0;
}
LyogVGhpcyBkb2MgaXMgdG8gaW52ZXN0aWdhdGUgdGhlIGlzc3VlIGJyb3VnaHQgYnkgcmVmZXJlbmNlIHJldHVybiB0eXBlIG9mIGEKICogZnVuY3RvciBhcmd1bWVudCBzdGQ6OmZ1bmN0aW9uLiBXZSBleHBlY3QgaXQgY2FuIHBhc3MgdGhlIGJ5cGFzcyBmdW5jdGlvbgogKiBkZWZpbmVkIGluIHRvcCBsYXllciB0byBsZXNzLWNvbnRleHQgYm90dG9tIGxheWVyIGFuZCBzdGlsbCB3b3JrIGFzIGRlc2lnbmVkLgogKiBIb3dldmVyIHdlIHNlZSB3ZWlyZCBiZWhhdmlvciB3aGVuIGl0IGlzIHN0ZDo6ZnVuY3Rpb248Y29uc3Qgc3RkOjpzdHJpbmcmKGludCk+LgogKiBJbnN0ZWFkLCBzdGQ6OmZ1bmN0aW9uPGNvbnN0IHN0cmluZyooaW50KT4gd29ya3MgZmluZS4uLgoqLwojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDx1bm9yZGVyZWRfbWFwPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgovLyBUaGlzIGNsYXNzIHN0b3JlcyB2ZWN0cm9yIG9mIG51bWJlcnMgYW5kIGRpdmlzb3JzLiBBUEkgZ2V0UmVtYWluZGVyUmluZyBwaWNrcwovLyB0aG9zZSBudW1iZXJzJyByZW1haW5kZXIgZXF1YWwgdG8gZ2l2ZW4gbnVtYmVyIGFmdGVyIGRpdmlzaW9uLiBCeXBhc3MgZnVuY3Rpb24KLy8gaXMgcGFzc2VkIGluIGFzIGFyZ3VtZW50IHRvIHByaW50IHRoZSBuYW1lcy4KY2xhc3MgRWxlbWVudHMgewpwdWJsaWM6CiAgICBFbGVtZW50cygpID0gZGVmYXVsdDsKICAgIEVsZW1lbnRzKGludDMyX3QgbWF4TnVtLCBpbnQzMl90IGRpdmlzb3IpIDogX2RpdihkaXZpc29yKSB7CiAgICAgICAgX2RhdGEuY2xlYXIoKTsKICAgICAgICBfZGF0YS5yZXNlcnZlKG1heE51bSk7CiAgICAgICAgZm9yIChpbnQzMl90IGkgPSAwOyBpIDwgbWF4TnVtOyBpKyspIHsKICAgICAgICAgICAgX2RhdGEucHVzaF9iYWNrKGkpOwogICAgICAgIH0KICAgIH0KCiAgICB2b2lkIGdldFJlbWFpbmRlclJpbmcoaW50MzJfdCBybWQsIGNvbnN0IHN0ZDo6ZnVuY3Rpb248Y29uc3Qgc3RyaW5nJihpbnQzMl90KT4mIGdldE5hbWUsIHN0cmluZyogb3V0cHV0KSB7CiAgICAgICAgb3V0cHV0LT5jbGVhcigpOwogICAgICAgIGZvciAoaW50MzJfdCBpIDogX2RhdGEpIHsKICAgICAgICAgICAgaWYgKGkgJSBfZGl2ID09IHJtZCkgewogICAgICAgICAgICAgICAgLy8gY3Jhc2hlcyBoZXJlLiBnZXROYW1lKGkpIHBvaW50aW5nIHRvIGFkZHJlc3MgMAogICAgICAgICAgICAgICAgKm91dHB1dCArPSBnZXROYW1lKGkpICsgIiAiOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKcHJpdmF0ZToKICAgIHZlY3RvcjxpbnQzMl90PiBfZGF0YTsKICAgIGludDMyX3QgX2RpdjsKfTsKCmludCBtYWluICgpIHsKICAgIHVub3JkZXJlZF9tYXA8aW50MzJfdCwgc3RyaW5nPiBudW1Ub1N0cjsKICAgIG51bVRvU3RyWzBdID0gIm51bGwiOwogICAgbnVtVG9TdHJbMV0gPSAiZWlucyI7CiAgICBudW1Ub1N0clsyXSA9ICJ6d2VpIjsKICAgIG51bVRvU3RyWzNdID0gImRyZWkiOwogICAgbnVtVG9TdHJbNF0gPSAidmllciI7CgogICAgLy8gVGhlIGZ1bmN0b3IKICAgIHN0ZDo6ZnVuY3Rpb248Y29uc3Qgc3RyaW5nJihpbnQzMl90KT4gZ2V0TmFtZSA9IFsmbnVtVG9TdHJdKGludDMyX3QgaSkgLT4gY29uc3Qgc3RyaW5nJiB7IHJldHVybiBudW1Ub1N0cltpXTsgfTsKCiAgICBFbGVtZW50cyBzbWFsbFJpbmcoNCwgMik7IC8vIGNvbnRhaW5zIHswLDEsMiwzfSwgZGl2aXNvcjogMgogICAgc3RyaW5nIHJlc3VsdDsKICAgIC8vIFRoaXMgaXMgYWN0dWFsbHkgdG8gZ2V0IGFsbCBvZGQgbnVtYmVycyA8IDQKICAgIHNtYWxsUmluZy5nZXRSZW1haW5kZXJSaW5nKDEsIGdldE5hbWUsICZyZXN1bHQpOwoKICAgIC8vIEJPT00hCiAgICBjb3V0IDw8IHJlc3VsdCA8PCBlbmRsOwoKICAgIHJldHVybiAwOwp9