how to solve following problem in C++? - c++

I have one template function which will take a pointer type and i have instantiated it before calling.
i have written function with its dummy implementation as follows:
template<T>fun_name( const T *p )
{
//written functionality which will give me class name that i will store into string Variable
e.g. i got output like this string Var = "First_class" or string Var = "Second_class"
//Using this class name i will call one function of that class
if(Var == "Fisrt_class")
{
First_class::static_function_name(p);
}
if(Var == "Second_class")
{
Second_class::static_function_name(p);
}
}
and in global scope i instantiated this function for two variables as like below:
template<first_class>static_function_name(const First_class *)
template<Second_class>static_function_name(const Second_class *)
above code gives me error that
error: no matching function call in Second_class::static_function_class(const Fisrt_class*)
error: no matching function call in First_class::static_function_class(const Second_class*)
thanks in advance!

I think this :
template<typename T> // template<class T> is equally valid!
void fun_name( const T *p )
{
T::static_function_name(p);
}
is enough!
Two more errors is fixed in the above code:
Mention the keyword typename in template<T> in your code. You can also write template<class T> which is equally valid.
Mention the return type of the function template as well.

Your function template "calls" each of the static functions in each class. Even though program flow may never get to one of the calls, the compiler still has to figure out the code for each of them.
So when you instantiate:
template<first_class>fun_name(const first_class*)
the compiler tries to compile the entire function with T = first_class, which means at some point inside the function, it will try to compile the function call:
Second_class::static_function_name(p);
But since variable p is a pointer to first_class, the compiler doesn't find the function.
If you want conditional compilation, try specializing your function instead so the compiler only compiles the function call you intended for each type:
template <T> fun_name (const T* p);
template <> fun_name<first_class>(const first_class* p) {
first_class::static_function_name(p);
}
template <> fun_name<second_class>(const second_class* p) {
second_class::static_function_name(p);
}
Alternatively, you can use member functions which seem to be intended for what you are trying to do here. Then you can create objects and call the functions directly:
first_class f;
second_class s;
f.function();
s.function();

try changing to ,
template<typename T>
void fun_name( const T *p )
{
T::static_function_name(p);
}

Related

How to rewrite template function to allow code reuse

Consider the following template recursion function. Its purpose is to create a vector containing all values in the enum class EnumClassName for which its associated predicate function bool xxx<N>() returns true.
template <EnumClassName N = EnumClassName::LAST_ENUM_VALUE>
std::vector<EnumClassName> xxx_stuff()
{
std::vector<EnumClassName> v = xxx_stuff<EnumClassName(static_cast<int>(N) - 1)>();
if (xxx<N>()) {
v.emplace_back(N);
}
return v;
}
with the recursion base case:
template <> std::vector<EnumClassName> xxx_stuff<EnumClassName::FIRST_ENUM_VALUE>()
{
return {};
}
Now assume there are 10 of these functions where the only thing that differs is the xxx name. I.e. we have the functions alpha_stuff with a corresponding predicate function alpha<N>, beta_stuff with a corresponding predicate function beta<N>, etc etc.
Is there any way to not duplicate the above function 10 times, where the only difference is the replacement of xxx with alpha, beta etc in each duplicate?
I am not able to just loop over the enum values, because the xxx<N> functions in turn call another function yyy<N> which will not accept a runtime-generated template argument <N> (forgive my lingo there, I actually have no idea what I'm talking about or how this works, I just know it gave me compilation errors when I tried it that way).
You cannot pass function template as argument or overloaded function, but you can wrap the call in a type, and then
template <typename EnumClassName,
EnumClassName N = EnumClassName::LAST_ENUM_VALUE,
typename F>
std::vector<EnumClassName> xxx_stuff(F&& f)
{
std::vector<EnumClassName> v =
xxx_stuff<EnumClassName, EnumClassName(static_cast<int>(N) - 1)>(f);
if (f(std::integral_constant<EnumClassName, N>{})) {
v.emplace_back(N);
}
return v;
}
with usage
auto v = xxx_stuff<E>([](auto n) { return xxx<n()>(); });
Demo
Note: That recursion can be avoided using std::integer_sequence.

is there a way to store a generic templated function pointer?

The Goal:
decide during runtime which templated function to use and then use it later without needing the type information.
A Partial Solution:
for functions where the parameter itself is not templated we can do:
int (*func_ptr)(void*) = &my_templated_func<type_a,type_b>;
this line of code can be modified for use in an if statement with different types for type_a and type_b thus giving us a templated function whose types are determined during runtime:
int (*func_ptr)(void*) = NULL;
if (/* case 1*/)
func_ptr = &my_templated_func<int, float>;
else
func_ptr = &my_templated_func<float, float>;
The Remaining Problem:
How do I do this when the parameter is a templated pointer?
for example, this is something along the lines of what I would like to do:
int (*func_ptr)(templated_struct<type_a,type_b>*); // This won't work cause I don't know type_a or type_b yet
if (/* case 1 */) {
func_ptr = &my_templated_func<int,float>;
arg = calloc(sizeof(templated_struct<int,float>, 1);
}
else {
func_ptr = &my_templated_func<float,float>;
arg = calloc(sizeof(templated_struct<float,float>, 1);
}
func_ptr(arg);
except I would like type_a, and type_b to be determined during runtime. I see to parts to the problem.
What is the function pointers type?
How do I call this function?
I think I have the answer for (2): simply cast the parameter to void* and the template function should do an implicit cast using the function definition (lease correct me if this won't work as I think it will).
(1) is where I am getting stuck since the function pointer must include the parameter types. This is different from the partial solution because for the function pointer definition we were able to "ignore" the template aspect of the function since all we really need is the address of the function.
Alternatively there might be a much better way to accomplish my goal and if so I am all ears.
Thanks to the answer by #Jeffrey I was able to come up with this short example of what I am trying to accomplish:
template <typename A, typename B>
struct args_st {
A argA;
B argB;
}
template<typename A, typename B>
void f(struct args_st<A,B> *args) {}
template<typename A, typename B>
void g(struct args_st<A,B> *args) {}
int someFunction() {
void *args;
// someType needs to know that an args_st struct is going to be passed
// in but doesn't need to know the type of A or B those are compiled
// into the function and with this code, A and B are guaranteed to match
// between the function and argument.
someType func_ptr;
if (/* some runtime condition */) {
args = calloc(sizeof(struct args_st<int,float>), 1);
f((struct args_st<int,float> *) args); // this works
func_ptr = &g<int,float>; // func_ptr should know that it takes an argument of struct args_st<int,float>
}
else {
args = calloc(sizeof(struct args_st<float,float>), 1);
f((struct args_st<float,float> *) args); // this also works
func_ptr = &g<float,float>; // func_ptr should know that it takes an argument of struct args_st<float,float>
}
/* other code that does stuff with args */
// note that I could do another if statement here to decide which
// version of g to use (like I did for f) I am just trying to figure out
// a way to avoid that because the if statement could have a lot of
// different cases similarly I would like to be able to just write one
// line of code that calls f because that could eliminate many lines of
// (sort of) duplicate code
func_ptr(args);
return 0; // Arbitrary value
}
Can't you use a std::function, and use lambdas to capture everything you need? It doesn't appear that your functions take parameters, so this would work.
ie
std::function<void()> callIt;
if(/*case 1*/)
{
callIt = [](){ myTemplatedFunction<int, int>(); }
}
else
{
callIt = []() {myTemplatedFunction<float, float>(); }
}
callIt();
If I understand correctly, What you want to do boils down to:
template<typename T>
void f(T)
{
}
int somewhere()
{
someType func_ptr;
int arg = 0;
if (/* something known at runtime */)
{
func_ptr = &f<float>;
}
else
{
func_ptr = &f<int>;
}
func_ptr(arg);
}
You cannot do that in C++. C++ is statically typed, the template types are all resolved at compile time. If a construct allowed you to do this, the compiler could not know which templates must be instanciated with which types.
The alternatives are:
inheritance for runtime polymorphism
C-style void* everywhere if you want to deal yourself with the underlying types
Edit:
Reading the edited question:
func_ptr should know that it takes an argument of struct args_st<float,float>
func_ptr should know that it takes an argument of struct args_st<int,float>
Those are incompatible. The way this is done in C++ is by typing func_ptr accordingly to the types it takes. It cannot be both/all/any.
If there existed a type for func_ptr so that it could take arguments of arbitrary types, then you could pass it around between functions and compilation units and your language would suddenly not be statically typed. You'd end up with Python ;-p
Maybe you want something like this:
#include <iostream>
template <typename T>
void foo(const T& t) {
std::cout << "foo";
}
template <typename T>
void bar(const T& t) {
std::cout << "bar";
}
template <typename T>
using f_ptr = void (*)(const T&);
int main() {
f_ptr<int> a = &bar<int>;
f_ptr<double> b = &foo<double>;
a(1);
b(4.2);
}
Functions taking different parameters are of different type, hence you cannot have a f_ptr<int> point to bar<double>. Otherwise, functions you get from instantiating a function template can be stored in function pointers just like other functions, eg you can have a f_ptr<int> holding either &foo<int> or &bar<int>.
Disclaimer: I have already provided an answer that directly addresses the question. In this answer, I would like to side-step the question and render it moot.
As a rule of thumb, the following code structure is an inferior design in most procedural languages (not just C++).
if ( conditionA ) {
// Do task 1A
}
else {
// Do task 1B
}
// Do common tasks
if ( conditionA ) {
// Do task 2A
}
else {
// Do task 2B
}
You seem to have recognized the drawbacks in this design, as you are trying to eliminate the need for a second if-else in someFunction(). However, your solution is not as clean as it could be.
It is usually better (for code readability and maintainability) to move the common tasks to a separate function, rather than trying to do everything in one function. This gives a code structure more like the following, where the common tasks have been moved to the function foo().
if ( conditionA ) {
// Do task 1A
foo( /* arguments might be needed */ );
// Do task 2A
}
else {
// Do task 1B
foo( /* arguments might be needed */ );
// Do task 2B
}
As a demonstration of the utility of this rule of thumb, let's apply it to someFunction(). ... and eliminate the need for dynamic memory allocation ... and a bit of cleanup ... unfortunately, addressing that nasty void* is out-of-scope ... I'll leave it up to the reader to evaluate the end result. The one feature I will point out is that there is no longer a reason to consider storing a "generic templated function pointer", rendering the asked question moot.
// Ideally, the parameter's type would not be `void*`.
// I leave that for a future refinement.
void foo(void * args) {
/* other code that does stuff with args */
}
int someFunction(bool condition) {
if (/* some runtime condition */) {
args_st<int,float> args;
foo(&args);
f(&args); // Next step: pass by reference instead of passing a pointer
}
else {
args_st<float,float> args;
foo(&args);
f(&args); // Next step: pass by reference instead of passing a pointer
}
return 0;
}
Your choice of manual memory management and over-use of the keyword struct suggests you come from a C background and have not yet really converted to C++ programming. As a result, there are many areas for improvement, and you might find that your current approach should be tossed. However, that is a future step. There is a learning process involved, and incremental improvements to your current code is one way to get there.
First, I'd like to get rid of the C-style memory management. Most of the time, using calloc in C++ code is wrong. Let's replace the raw pointer with a smart pointer. A shared_ptr looks like it will help the process along.
// Instead of a raw pointer to void, use a smart pointer to void.
std::shared_ptr<void> args;
// Use C++ memory management, not calloc.
args = std::make_shared<args_st<int,float>>();
// or
args = std::make_shared<args_st<float,float>>();
This is still not great, as it still uses a pointer to void, which is rarely needed in C++ code unless interfacing with a library written in C. It is, though, an improvement. One side effect of using a pointer to void is the need for casts to get back to the original type. This should be avoided. I can address this in your code by defining correctly-typed variables inside the if statement. The args variable will still be used to hold your pointer once the correctly-typed variables go out of scope.
More improvements along this vein can come later.
The key improvement I would make is to use the functional std::function instead of a function pointer. A std::function is a generalization of a function pointer, able to do more albeit with more overhead. The overhead is warranted here in the interest of robust code.
An advantage of std::function is that the parameter to g() does not need to be known by the code that invokes the std::function. The old style of doing this was std::bind, but lambdas provide a more readable approach. Not only do you not have to worry about the type of args when it comes time to call your function, you don't even need to worry about args.
int someFunction() {
// Use a smart pointer so you do not have to worry about releasing the memory.
std::shared_ptr<void> args;
// Use a functional as a more convenient alternative to a function pointer.
// Note the lack of parameters (nothing inside the parentheses).
std::function<void()> func;
if ( /* some runtime condition */ ) {
// Start with a pointer to something other than void.
auto real_args = std::make_shared<args_st<int,float>>();
// An immediate function call:
f(real_args.get());
// Choosing a function to be called later:
// Note that this captures a pointer to the data, not a copy of the data.
// Hence changes to the data will be reflected when this is invoked.
func = [real_args]() { g(real_args.get()); };
// It's only here, as real_args is about to go out of scope, where
// we lose the type information.
args = real_args;
}
else {
// Similar to the above, so I'll reduce the commentary.
auto real_args = std::make_shared<args_st<float,float>>();
func = [real_args]() { g(real_args.get()); };
args = real_args;
}
/* other code that does stuff with args */
/* This code is probably poor C++ style, but that can be addressed later. */
// Invoke the function.
func();
return 0;
}
Your next step probably should be to do some reading on these features so you understand what this code does. Then you should be in a better position to leverage the power of C++.

How to compile-time detect functions that overloaded important template?

Suppose we have a template:
template <class T>
void VeryImportantFunction(T t) {
// something
}
Somewhere it is called with something like:
// ..
int a = 12345;
VeryImportantFunction(a);
// ..
It is very big project with tons of source code, and occasionally somewhere in deep of the code appears a new header with overloaded function:
void VeryImportantFunction(int t) {
// totally another behavior
}
And code fragment above will call overloaded function, because it have more priority.
Can we somehow disable or in another way compile-time detect functions that can overload our important template?
Your question is unclear, but here's my take on it.
If you want to hit the template overload, you can simply invoke the function by explicitly specifying the template parameters:
int a = 12345;
VeryImportantFunction<int>(a);
If you want this from happening again in the future, then make VeryImportantFunction either a lambda or a struct - those cannot be overloaded "externally":
inline const auto VeryImportantFunction = [](auto x){ /* ... */ };
// no one can overload this!
If you want to know all the overloads of VeryImportantFunction without external tooling, then call it in a completely wrong way - the compiler error will likely show all considered overloads:
VeryImportantFunction(5, 5, 5, 5);
// error... will likely show all candidates
Write
inline void VeryImportantFunction(int t)
{
VeryImportantFunction<int>(t); // call the template function
}
immediately after your template definition.
Then if someone has written their own version of void VeryImportantFunction(int t), you'll get a compiler error.

Compiler error wrapping an interpretable function

I have a legacy C code base, which I am migrating to C++ in a piecemeal fashion. It includes an interpreter, so there is a need to wrap static functions and arguments for use by the interpreter. So a typical function for export to the interpreter may have the following signature:
static void do_strstr(struct value * p)
and be exposed to the interpreter like so:
using vptr = void (*) ();
template <typename Func>
constexpr vptr to_vptr(Func && func)
{ return reinterpret_cast<vptr>(func); }
struct function string_funs[] = {
...
{ C_FN3, X_A3, "SSI", to_vptr(do_strstr), "find" },
...
};
This has been proven to work. The drawback with the method so far is that the called function must allocate memory onto a temporary stack. An improvement would be where the called function just returns a string, for example. This function is then wrapped, where the wrapper does the memory magic behind the scenes. This allows functions to created in a more vanilla way.
Here is an implementation which concatenates two strings using my improved method:
static std::string do_concata(struct value* p)
{
std::string s1 = (p)->gString();
std::string s2 = (p+1)->gString();
return s1+s2;
}
I create a helper function:
static void do_concata_1(struct value* p)
{
wrapfunc(do_concata)(p);
}
where the somewhat generic wrapper is defined as:
std::function<void(struct value*)>
wrapfunc(std::function<std::string(struct value*)> func)
{
auto fn = [=](struct value* p) {
std::string s = func(p);
char* ret = alloc_tmp_mem(s.size()+1);
strcpy(ret, s.c_str());
p->sString(ret);
return;
};
return fn;
}
which is exposed to the interpreter as follows:
struct function string_funs[] = {
...
{ C_FN2, X_A2, "SS", to_vptr(do_concata_1), "concata" },
...
};
I am not satisfied with this solution, though, as it requires a helper function for each function I define. It would be better if I could eliminate do_concata_1 and write another function that wraps the wrapfunc.
And this is where the problem is. If I write:
vptr to_vptr_1(std::function<void(struct value*)> func)
{
return to_vptr(wrapfunc(func));
}
then the compiler complains:
stringo.cc: In function ‘void (* to_vptr_1(std::function<void(value*)>))()’:
stringo.cc:373:30: error: could not convert ‘func’ from ‘std::function<void(value*)>’ to ‘std::function<std::__cxx11::basic_string<char>(value*)>’
return to_vptr(wrapfunc(func));
which is bizarre in my mind, because where did the std::__cxx11::basic_string<char> come from? It should be void, surely?
I'm at a loss to see what the fix should be. I am also a bit confused as to whether I should be passing copies of functions, references to functions, or the enigmatic && r-vale references.
In to_vptr_1(), func is established as a function that returns void. But func is passed to wrapfunc(), which expects a function that returns std::string. The compiler does not have a way to convert func from std::function<void(struct value*)> to std::function<std::string(struct value*)>, so it emits the error message.
reinterpret_cast from std::function to raw function pointer is not going to work. This question has some good discussion on the topic, and this one has a solution that could perhaps be reworked for this situation.

Sending a templated function as an argument to a templated function in D

I'm trying to send D's sort function as a template argument to the pipe function. When I use sort without template arguments it works:
import std.stdio,std.algorithm,std.functional;
void main()
{
auto arr=pipe!(sort)([1,3,2]);
writeln(arr);
}
However, when I try to use sort with a template argument:
import std.stdio,std.algorithm,std.functional;
void main()
{
auto arr=pipe!(sort!"b<a")([1,3,2]);
writeln(arr);
}
I get an error - main.d(5): Error: template instance sort!("b<a") sort!("b<a") does not match template declaration sort(alias less = "a < b",SwapStrategy ss = SwapStrategy.unstable,Range)
Why does it happen? sort!"b<a" works on it's own, and it has the same arguments and return types as sort, so why does pipe accept sort but not sort!"b<a"? And is there a correct syntax for what I try to do?
UPDATE
OK, I've tried to wrap the sort function. The following code works:
import std.stdio,std.algorithm,std.functional,std.array;
template mysort(string comparer)
{
auto mysort(T)(T source)
{
sort!comparer(source);
return source;
}
}
void main()
{
auto arr=pipe!(mysort!"b<a")([1,3,2]);
writeln(arr);
}
So why doesn't the original version work? is this because of the extra template parameters sort takes?
Yes it's because of the extra template parameters — specifically the Range parameter. The problem can be reduced to
size_t sort2(alias f, Range)(Range range)
{
return 0;
}
alias sort2!"b<a" u;
The instantiation sort!"b<a" will fail because the Range is not determined. The function call sort2!"b<a"([1,2,3]) works because the parameter [1,2,3] can tell the compiler the type Range is int[]. This is known as "implicit function template instantiation (IFTI)". But IFTI only works when it is used as a function. In your use case, sort!"b<a" is instantiated without providing all parameters, thus the error.
This can be fixed by making the input a function literal, which is just similar to your mysort solution:
auto arr = pipe!(x => sort!"b<a"(x))([1,3,2]);
Or you could provide all required template parameters. This makes the code very unreadable though.
auto arr = pipe!(sort!("b<a", SwapStrategy.unstable, int[]))([1,3,2]);