C++
This program works by opening its own source file, extracting the desired function, writing it to a new source file (which prints the result), compiling it, then executing it and reading its output.
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
using namespace std;
//=== here's all our "callable" functions ===
int add (int a, int b) {
return a + b;
}
int indexof (const char *str, char c) {
for (int n = 0; str[n]; ++ n) {
if (str[n] == c)
return n;
}
return -1;
}
const char * addsuffix (int n) {
static char buffer[20];
switch (n % 10) {
case 1: sprintf(buffer, "%dst", n); break;
case 2: sprintf(buffer, "%dnd", n); break;
default: sprintf(buffer, "%dth", n); break;
}
return buffer;
}
//=== end of "callable" functions ===
int count (const char *s, int c) {
int n = 0;
while (*s)
n += (*(s ++) == c);
return n;
}
template <typename ReturnType>
ReturnType icall (const char *fn, const char *p) {
// generate output
ifstream me(__FILE__);
ofstream out("temp~.cpp");
char line[1000];
int infunc = 0;
while (!me.eof()) {
me.getline(line, sizeof(line));
if (!strncmp(line, "#include", 8))
out << line << endl;
else if (!strncmp(line, "using", 5))
out << line << endl;
else {
if (!infunc) {
char *fname = strstr(line, fn);
if (fname) {
infunc += 1;
*fname = 0;
out << line << "oneTrickPony" << (fname + strlen(fn)) << endl;
*fname = ' ';
}
} else {
out << line << endl;
}
if (infunc)
infunc += count(line, '{') - count(line, '}');
if (strchr(line, '}') && infunc == 1)
break;
}
}
out << "int main () { cout << oneTrickPony(" << p << "); }" << endl;
out.close();
// compile output
system("g++ temp~.cpp -o temp~.exe"); // exe suffix ok on linux
// execute output
FILE *res = popen("temp~.exe", "r");
fgets(line, sizeof(line), res);
pclose(res);
// parse output
ReturnType rval;
stringstream rss(line);
rss >> rval;
return rval;
}
#define call(rt,fn,p...) icall<rt>(fn, #p)
int main () {
// call functions and store results
int resulta = call(int, "add", 14, 99);
int resultn = call(int, "indexof", "abcdefg", 'e');
string results = call(string, "addsuffix", 1);
// print results
cout << resulta << endl
<< resultn << endl
<< results << endl;
}
The icall
function is responsible for doing all the dirty work; the template type is the return type and is used for parsing the output into a usable value. The call
macro exists to allow us to write a variable number of function parameters to the generated source file. The calls are made in main
:
// call functions and store results
int resulta = call(int, "add", 14, 99);
int resultn = call(int, "indexof", "abcdefg", 'e');
string results = call(string, "addsuffix", 1);
Requires gcc. Tested on MinGW.
Supports:
- Any return types supported by the
istream
>>
operator.
- Runtime function names.
- Any number of parameters, of any type.
Does not support:
- Non-constant function parameters. This is a tradeoff for number 3 and also for brevity. I could add support for this by dropping the macro and using more templates, but I didn't want to add too much code to distract from the general idea.
- Functions with
void
return types. A specialized icall
that does not parse the returned value would allow this. Again, didn't go too crazy.
A little messy but gets the job done. It's pretty good at parsing itself but will fail under certain conditions (e.g. if a curly brace appears in a string, or the function name appears before the function in another context... I didn't really want to implement a full-on C++ parser...).
Here is an example generated file for a call to indexof
:
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
using namespace std;
int oneTrickPony (const char *str, char c) {
for (int n = 0; str[n]; ++ n) {
if (str[n] == c)
return n;
}
return -1;
}
int main () { cout << oneTrickPony("abcdefg", 'e'); }
I am voting to close this as too broad because we require objective validity criteria for all challenges. As it stands, there is no clear way to determine the validity of a submission. Additionally, there is no specification of the behavior of a valid submission. – Mego – 2016-03-31T07:14:44.277
1Here on this site you need to specify an objective winning criterion to decide the winner of the challenge. I would recommend you to tag this as a popularity contest, meaning that the answer with the most upvotes will be accepted. – user12205 – 2014-03-01T00:52:37.450
Got it, tagged appropriately. – None – 2014-03-01T00:53:12.287
58+10471 ... nice – qwr – 2014-03-01T01:11:48.730
+10741 I can't stop to laugh with this. – Victor Stafusa – 2014-03-01T01:16:45.420
1144K rep??????? – TheDoctor – 2014-03-01T01:18:15.247
29I wonder how much rep you need to overflow stack overflow? – PyRulez – 2014-03-01T03:07:45.967
34
Apparently this is a screencap from @Mysticial's account, seeing the avatar. Mysticial, could you please just *click on your rep tab?!?!?!*
– Doorknob – 2014-03-01T03:30:09.1034@Doorknob Why should he? Its all coming from one answer. – FDinoff – 2014-03-01T03:37:25.390
8@PyRulez Jon Skeet hasn't yet, so we're safe for now. – Cole Johnson – 2014-03-01T05:14:07.500
I wonder how @AlexM. got that picture, unless he is Mysticial himself. In that case, why did he start a new account? – None – 2014-03-02T01:22:50.080
3
@user2509848 He posted that picture in the Lounge for users with less than 10k who cannot see closed questions.
– fredoverflow – 2014-03-02T07:03:32.9931What I want to know is how the hell do you generate THAT much rep??? – WallyWest – 2014-03-03T09:33:52.767
1
@WallyWest Well, his top answer has over 10,000 upvotes :)
– fredoverflow – 2014-03-04T08:23:07.963@WallyWest you write an excellent answer to a tricky question. Try reading his. – Thorbjørn Ravn Andersen – 2014-03-04T09:17:05.967
2
@ColeJohnson you are terribly wrong! If you try to run this query on Jon Skeets account it will overflow!
– Tomas – 2014-03-04T22:34:11.800I like how you can just use
method.__call__()
in Python. :P – cjfaure – 2014-03-06T22:07:22.520@PyRulez Let's hope there's a cap at
2^64-1
rep, where it doesn't allow it to go any higher so it can't overflow. If so, I wonder if you get some kind of "god status" for attaining that, of if there's some sort of "extended rep" after reaching the 64-bit limit. – Braden Best – 2014-04-14T17:42:36.873Would a destructor function count? In deplhi when I define a destructor it will be called by using
Tobject.free
which isnt really a call of function X – Teun Pronk – 2014-04-16T08:27:51.257