I'm wondering how exactly this code works in detail (e.g. how is it able to directly access the value of TYPE).
I saw this code in a larger codebase (which is non-public, so the example is paraphrased). I've never seen this specific use-case. Is passing a template parameter like this common? Does it have a specific name/is this an idiom/pattern? When would you use this and why?
#include <iostream>
namespace FileA
{
struct Foo
{
enum TYPE
{
ENTRY,
};
void callme()
{
std::cout << "Foo\n";
}
};
}
namespace FileB
{
template <typename T>
void fun(T& obj)
{
std::cout << T::ENTRY << "\n";
obj.callme();
}
}
int main()
{
FileA::Foo f;
FileB::fun(f);
}
This will print:
0
Foo
a template is a kind of macro in the general sense of the term, so if you "expand" FileB::fun(f); T is replaced by the type of f being FileA::Foo and it is like if you have :
void fun(FileA::Foo& obj)
{
std::cout << FileA::Foo::ENTRY << "\n";
obj.callme();
}
because FileA::Foo::ENTRY is 0 the std::cout writes 0, then you apply FileA::Foo::callme() whose prints Foo
Warning, a template is much more than that, it is just a very simplified explanation of how that example works and produces the outputs, do not take it literally please ^^
Related
So I've found a variety of articles and posts saying that there is no way to convert typename to string but I haven't found one about the opposite. I have a template of a function with specializations:
template <typename T>
void foo(T sth) {}
template <>
void foo<int>(int sth) {}
...
and I'm reading from a file constructed like this:
int 20
double 12.492
string word
Is there a way to call the correct specialization of foo() depending on the content of the file?
Yes there is, but it requires manual code and that you know all the types that are going to appear in the file. That's because templates are compile time constructs and they cannot be instantiated at runtime.
You can always use the preprocessor or other tricks to try and reduce the boilerplate if you want to.
void callFoo(std::string type, std::any arg) {
if (type == "int")
foo<int>(std::any_cast<int>(arg));
else if (type == "double")
foo<double>(std::any_cast<double>(arg));
else if (type == "string")
foo<std::string>(std::any_cast<std::string>(arg));
}
Of course, this requires that you pass in the correct type (no implicit conversions!). I don't see any way to avoid that.
To be honest, I am not sure about understanding your question. As I interpret it, I believe that you do not need a kind of dispatcher in running time neither to compute a string containing the type name. Simply you write a general template function that calls a special template wrapper that disambiguates the call to foo() according to the type. You require that the specialized foo() receives a second special parameter (the_type<T>) which is used for disambiguating.
Here a full and operating demo:
# include <string>
# include <iostream>
using namespace std;
template<class T> struct the_type { using type = T; };
template <typename T>
void foo(const T par)
{
foo(par, the_type<T>());
}
void foo(int par, the_type<int>)
{
cout << "int " << par << endl;
}
void foo(double par, the_type<double>)
{
cout << "double " << par << endl;
}
void foo(const string & par, the_type<string>)
{
cout << "string " << par << endl;
}
void foo(const char * par, the_type<const char*>)
{
cout << "char* " << par << endl;
}
int main()
{
foo(20);
foo(12.492);
foo("word");
foo(string("word"));
}
whose output is:
int 20
double 12.492
char* word
string word
If you need another specialization, then you simply define it. In some cases, you will have to explicitly to define the specialization as the template parameter.
You could use macro manips for avoiding repetitive things. For example, given that foo() structure is the same, you could encapsulate it in a macro. Something like this:
# define GENFOO(type_name) \
void foo(type_name par, the_type<type_name>) \
{ \
cout << #type_name " " << par << endl; \
}
GENFOO(int);
GENFOO(double);
GENFOO(string)
However, I would say that each specialized version of foo() would not be so similar.
So I've found a variety of articles and posts saying that there is no way to convert typename to string but I haven't found one about the opposite. I have a template of a function with specializations:
template <typename T>
void foo(T sth) {}
template <>
void foo<int>(int sth) {}
...
and I'm reading from a file constructed like this:
int 20
double 12.492
string word
Is there a way to call the correct specialization of foo() depending on the content of the file?
Yes there is, but it requires manual code and that you know all the types that are going to appear in the file. That's because templates are compile time constructs and they cannot be instantiated at runtime.
You can always use the preprocessor or other tricks to try and reduce the boilerplate if you want to.
void callFoo(std::string type, std::any arg) {
if (type == "int")
foo<int>(std::any_cast<int>(arg));
else if (type == "double")
foo<double>(std::any_cast<double>(arg));
else if (type == "string")
foo<std::string>(std::any_cast<std::string>(arg));
}
Of course, this requires that you pass in the correct type (no implicit conversions!). I don't see any way to avoid that.
To be honest, I am not sure about understanding your question. As I interpret it, I believe that you do not need a kind of dispatcher in running time neither to compute a string containing the type name. Simply you write a general template function that calls a special template wrapper that disambiguates the call to foo() according to the type. You require that the specialized foo() receives a second special parameter (the_type<T>) which is used for disambiguating.
Here a full and operating demo:
# include <string>
# include <iostream>
using namespace std;
template<class T> struct the_type { using type = T; };
template <typename T>
void foo(const T par)
{
foo(par, the_type<T>());
}
void foo(int par, the_type<int>)
{
cout << "int " << par << endl;
}
void foo(double par, the_type<double>)
{
cout << "double " << par << endl;
}
void foo(const string & par, the_type<string>)
{
cout << "string " << par << endl;
}
void foo(const char * par, the_type<const char*>)
{
cout << "char* " << par << endl;
}
int main()
{
foo(20);
foo(12.492);
foo("word");
foo(string("word"));
}
whose output is:
int 20
double 12.492
char* word
string word
If you need another specialization, then you simply define it. In some cases, you will have to explicitly to define the specialization as the template parameter.
You could use macro manips for avoiding repetitive things. For example, given that foo() structure is the same, you could encapsulate it in a macro. Something like this:
# define GENFOO(type_name) \
void foo(type_name par, the_type<type_name>) \
{ \
cout << #type_name " " << par << endl; \
}
GENFOO(int);
GENFOO(double);
GENFOO(string)
However, I would say that each specialized version of foo() would not be so similar.
Is it possible to recognize all calling of a certain function in everywhere
function1<T1>(); function1<T4>(); ...
then add a line that calling this following line in a certain place?
function2<T1>(); function2<T4>(); ...
For example,
class X{
template <class T> function1(){ }
template <class T> function2(){ }
}
class A{}
class B{}
class C{}
int main(){
X x;
//vvvv this code (hopefully) will be auto generated (by macro?)
x.function2<A>();
x.function2<B>(); //<--- I don't care about order of A or B
//x.function2<C>(); //<--- this line should not be generated
//^^^^ Only X's function1 should be recognized,
// not other class's functions with the same name.
x.function1<B>();
x.function1<A>();
x.function1<B>(); .... // called in various places in many .cpp
//If it is called in another .cpp, but not here, it should still be recognized
}
Edit
My old code call :-
function2<T>() inside function1<T>()
It costs CPU significantly (I profiled), because function1 have to check whether function2 was called or not every time.
Here is a draft of a near-zero overhead solution that will work only if you are not going to invoke function1() before main():
#include <iostream>
#include <typeinfo>
template <class T>
void function2()
{
std::cout << "function2<" << typeid(T).name() << ">()" << std::endl;
}
bool dummy = true;
template <class T>
struct Func1WasInstantiated
{
struct CallFunc2
{
CallFunc2() { function2<T>(); }
void operator()() const { dummy = false; }
};
static CallFunc2 callFunc2;
};
template <class T>
typename Func1WasInstantiated<T>::CallFunc2 Func1WasInstantiated<T>::callFunc2;
template <class T>
void function1()
{
Func1WasInstantiated<T>::callFunc2();
std::cout << "function1<" << typeid(T).name() << ">()" << std::endl;
}
int main()
{
std::cout << "------- Entered main() ---------" << std::endl;
function1<int>();
function1<double>();
function1<int>();
return 0;
}
Output (check it on IDEONE):
function2<i>()
function2<d>()
------- Entered main() ---------
function1<i>()
function1<d>()
function1<i>()
The global variable dummy is the acceptor of the side effect, that ensures that Func1WasInstantiated<T>::callFunc2 is linked into the program and makes the code work as intended. Without the side effect contained in callFunc2() I can imagine an aggressively optimizing compiler eliminating that line from function1() (that is normal) and letting the linker leave out the callFunc2 objects as they become unreferenced (I cannot judge whether this would be against the C++ standard or not).
I'm using a timer library in Arduino IDE that has a function which takes "void(*func)(void)" as a parameter and runs it after certain time.I need to pass a function in my code with that library, the problem is I need "n" functions that do the same thing (just the variables involved inside the function take different values, which I take from an array of struct), that's why I can't use only one function and I need to be able to compile different functions with identical syntax but different variables involved.
I don't know how I can resolve this, what I want to do is to be able to create functions like in a for loop,
for(int i=0;i<MAX_FUNC;i++)
{
void func[i](){
x= structuredata.x[i];
}
}
I know this syntax is completely wrong but I'd like to know how can I achieve something like this . I tried using classes instead, but the library didn't let me use void functions created in a class as parameters, it indicated "unresolved overloaded function type"
If you're into template overrides and can restructure your functions as such, a solution to packing up a stack of callbacks to be fired consecutively is closer than you may think. You can make this more generic if the consistency of the function is literally identical. I.e. you can do this instead:
#include <iostream>
int ar[5] = { 1,2,3,4,5 };
// your function here
template <int i>
void callback()
{
// your code here. i is provided
int x = ar[i];
std::cout << "Got Value: " << x << '\n';
};
////////////////////////////////////////////////////////////
// unraveller
template<int N>
void callback_set()
{
callback_set<N-1>();
callback<N-1>();
}
// base callback set
template<>
void callback_set<0>() {}
////////////////////////////////////////////////////////////
int main()
{
callback_set<3>();
return 0;
}
Output
Got Value: 1
Got Value: 2
Got Value: 3
You "register" callback_set<N> as your callback, and it will chain up the calls to your function(s) for you. If individualized access to different implementations is needed, you can still to that, using full specializations:
#include <iostream>
// prototypes
template <int i>
void callback() {};
// your functions here
template<>
void callback<0>()
{
std::cout << "Callback #0" << '\n';
}
template<>
void callback<1>()
{
std::cout << "Callback #1" << '\n';
}
template<>
void callback<2>()
{
std::cout << "Callback #2" << '\n';
}
////////////////////////////////////////////////////////////
// unraveller
template<int N>
void callback_set()
{
callback_set<N-1>();
callback<N-1>();
}
// base callback set
template<>
void callback_set<0>() {}
////////////////////////////////////////////////////////////
int main()
{
callback_set<3>();
return 0;
}
Output
Callback #0
Callback #1
Callback #2
In essence you style-up your registered callback using callback_set<N> where N is the number of callbacks you've provided overrides for. Just a thought, but seems like it would be a fairly elegant solution to your problem if I understand it correctly.
You need some metaprogramming for that...
const int MAX_FUNC = 1000;
typedef void (*Tcallback)();
struct Tdata
{
int whatever;
};
Tdata callbackData[MAX_FUNC];
Tcallback callbacks[MAX_FUNC];
template <int index>
void callbackToIndex()
{
// callback knows it's index and thus can access some global structure for it's data
printf("%u", index);
callbackData[index];
}
template <int index>
void callbackCreate()
{
callbacks[index] = &callbackToIndex<index>;
callbackCreate<index - 1>();
}
template <>
void callbackCreate<-1>()
{
}
void create()
{
callbackCreate<MAX_FUNC - 1>();
}
consider this simple and pointless code.
#include <iostream>
struct A {
template<int N>
void test() {
std::cout << N << std::endl;
}
};
int main() {
A a;
a.test<1>();
}
It is a very simple example of a function template. What if however, I wanted to replace A::test with an overloaded operator() to make it a functor?
#include <iostream>
struct A {
template<int N>
void operator()() {
std::cout << N << std::endl;
}
};
int main() {
A a;
a<1>(); // <-- error, how do I do this?
}
Certainly if the operator() took parameters which were dependent on the template, the compiler could possibly deduce the template. But I just can't figure out the proper syntax to specify template parameters with a parameterless functor.
Is there a proper way to do this?
Obviously, this code would work since it bypasses the functor syntax:
a.operator()<1>();
but that kinda defeats the purpose of it being a functor :-P.
You can only call
a.operator()<1>();
but that would not be using a functor. Functors need a non template operator(), as they must be able to be called as varname() and that won't work with your code.
To make it a real functor change your code a template class (functors are classes):
#include <iostream>
template<int N>
struct A {
void operator()() {
std::cout << N << std::endl;
}
};
int main() {
A<1> a;
a();
}
There's not another "direct" way I know other than the:
a.operator()<1>();
syntax. If you're open to changing the code, moving the template parameter to the class would work, or using a (boost|tr1)::bind to make a (boost|tr1)::function object.
You are trying to pass a template parameter to an instance of an object, which as far as I know is not allowed. You can only pass templates parameters to template functions or template objects.
a.test<1>(); and a.operator()<1>(); work because they are serving as template functions.
Use boost::bind (check out boost libraries) to fix it though.
struct A {
void operator()(int n) {
std::cout << n << std::endl;
}
};
int main(int argc, char* argv[]) {
A a;
boost::function<void()> f = boost::bind<void>(a, 1);
f(); // prints 1
return 0;
}
And you don't even have to mess with templates!
You're stuck. Have you considered something like
struct A {
template<int N>
struct B
{
void operator()()
{ std::cout << N << std::endl; }
};
template<int N>
B<N> functor() {return B<N>();}
};
int main()
{
A a;
a.functor<1>()();
}
Nope, there's no way around it. Like you said, you have to either call the operator explicitly (which defeats the purpose), or the template arguments must be able to be deduced by the compiler.