Passing functions as variadic template arguments, and calling them [duplicate] - c++

This question already has answers here:
Ambiguous overload on argument-less variadic templates
(2 answers)
Closed 4 years ago.
I want to create a "grand total" function by summing several other functions together. This can be done at compile time, so I thought a recursive variadic function template would be a good solution. My code so far:
int One(){return 1;}
int Two(){return 2;}
int Three(){return 3;}
using func_t = int(void);
//Base case
template <func_t F>
int Total() {
return F();
}
template <func_t F, func_t... Fs>
int Total() {
return F() + Total<Fs...>();
}
int main(int argc, char *argv[])
{
cout << Total<One, Two, Three>() << endl;
return 0;
}
However, I get MSVC compiler error C2668: 'Total': ambiguous call to overloaded function; could be int Total<int Three(void),>(void) or int Total<int Three(void)>(void)
I don't understand why the compiler has two similar candidates for my function template, the only difference being that one has an extra comma.

Your base case declaration is incorrect, and results in the compiler being unable to differentiate between a call to your base case and a call to your recursive base.
If you make your base case an empty list of templates, there is no longer ambiguity.
template <class none = void>
int Total() {
return 0;
}

Related

C++ template: Derived class cannot resolute Base class function unless using "this->" [duplicate]

This question already has answers here:
Why do I have to access template base class members through the this pointer?
(3 answers)
ISO C++ Standard - rules regarding examining dependent base. Why?
(1 answer)
Closed 8 months ago.
This code doesn't compile:
#include<iostream>
using namespace std;
template<class T>struct Base {
void f(int) { cout << "Base::f() int\n"; }
};
template<class T>struct Derived:Base<T> {
void g(int i) { f(i); } // should be this->f(i) to pass compile
};
int main(){
Derived<char> obj;
obj.g(1); // cfunction short
return 0;
}
I googled and search on stackoverflow, it says that in the error-line, I should use write either
void g(int i) { this->f(i); }
or
void g(int i) { Base<T>::f(i); }
Yes, they work. I tried none-template version, doesn't need this complex qualifier. As long as both f() and g() doesn't use any template type parameter, I didn't think of a rule on template deduction upon these 2 functions.
Is this some hidden rule behind template resolution that I should add extra qualifier, and why my original code fail to compile?

Template explicit specialization in class using inheritance

Yesterday I asked about template explicit specialization in class.
Link.
Now I have the same purpose but now I wanna use inheritance to avoid code duplication. If I declare a function in the base class I cannot declare specialization of this function in the derived class.
My code:
#include <stdexcept>
#include <iostream>
class Base
{
public:
template <typename T>
T fun()
{
throw std::runtime_error("Unsupported template param");
}
};
class Derived : public Base
{
};
template <>
bool Base::fun<bool>()
{
return true;
}
template <>
float Derived::fun<float>()
{
return 5.6f;
}
template <>
double Derived::fun<double>()
{
return 5.684;
}
int main()
{
Derived d;
bool d_b = d.fun<bool>();
float d_f = d.fun<float>();
double d_d = d.fun<double>();
char d_error = d.fun<char>();
}
VS code errors:
use of inherited members is not allowed
g++
error: template id "fun" for "float Derived :: fun ()" does not match any template declaration
Intel C++ compiler:
source/app.cpp:25:16: error: no function template matches function template specialization 'fun'
float Derived::fun<float>()
^
source/app.cpp:30:1: error: extraneous 'template<>' in declaration of variable 'fun'
template <>
^~~~~~~~~~~
source/app.cpp:31:17: error: redefinition of 'fun' as different kind of symbol
double Derived::fun<double>()
^
source/app.cpp:25:16: note: previous definition is here
float Derived::fun<float>()
If it is impossible in C++, please answer another question: what is a wide-known practice in c++ to do what I want. Before I used D language and one man says me I don't ask a question "Why" to myself. And instead, I just try to transfer D methods to C++. I agree. That's why I ask.
Maybe a better way is to ignore templates and declare separated functions? For example:
funToBool()
funToFloat()
funToDouble()
This will compile if you add a public template definition of fun in Derived.
But that will probably not do what you want.
In particular d.fun<bool>(); will not execute the implementation in Base, but the implementation in Derived.
You cannot specialize template functions in derived classes.
You also cannot use subtype polymorphism on template functions: template cannot be virtual.
You can achieve some type of static polymorphism using CRTP.
Yes removing templates and working with separated functions would work (a.toX()...).
Another option is to work with overloads (i.e. passing a dummy argument or the destination variable and write different implementations).
Adding an example for the dummy argument solution as requested:
namespace TO {
static const bool BOOL = false;
static const double DOUBLE = 0.0;
static const int INT = 0;
}
struct A {
bool convert(bool dummy) {
return true;
}
};
struct B : public A {
using A::convert; // important
int convert(int dummy) {
return 2;
}
double convert(double dummy) {
return 3.0;
}
};
int main() {
B b;
std::cout << b.convert(TO::BOOL) << std::endl;
std::cout << b.convert(TO::DOUBLE) << std::endl;
std::cout << b.convert(TO::INT) << std::endl;
}
With this kind of solution there is a risk of implicit conversion when calling the function. toX() might be a safer option.

C++: std::apply with overloaded member function [duplicate]

This question already has answers here:
Is there any way in C++ to refer to a function template while neither calling it nor supplying its template parameters?
(4 answers)
Convert template function to generic lambda
(2 answers)
How do I make a functor out of an arbitrary function?
(2 answers)
Closed 2 years ago.
I have a function returning a std::pair, which I want to use to call an overloaded member function. I am not aware of any way to unpack a tuple in-place (which I'd prefer), so std::apply is my best bet, I think.
This works with a combination of tuple_cat and forward_as_tuple when the member function is not overloaded, but otherwise, the compiler complains about an unresolved overload.
That is understandable, given that std::apply just takes a function pointer, but I'd still like to know whether it can be made to work in a readable way.
Here's some example code:
#include <iostream>
#include <tuple>
#include <utility>
std::pair<int, int> func() { return { 0, 1 }; }
class MyClass {
public:
int memFun(int);
int memFun(int, int);
};
int MyClass::memFun(int i){ return 2*i; }
int MyClass::memFun(int a, int b){ return a+b; }
int main(){
MyClass myClass;
/* works */
std::pair pair { func() };
int number { myClass.memFun( pair.first, pair.second ) };
/* doesn't work (unresolved overload) */
int number { std::apply(
&MyClass::memFun,
std::tuple_cat( std::forward_as_tuple(myClass), func() )
) };
std::cout << number << "\n";
return 0;
}
Is there an elegant (=readable) way to do this without a temporary?
I only found this question and so far don't think it fully applies.

How to declare reference to lambda in C++ [duplicate]

This question already has answers here:
Is auto as a parameter in a regular function a GCC 4.9 extension?
(2 answers)
Closed 5 years ago.
I want to declare a function that takes as argument a function (or lambda) with a specific prototype.
The first try is:
#include <iostream>
using namespace std;
int test(int (&val)(int)) {
return val(2);
}
int main() {
cout << test([](int v){
return v+100;
});
return 0;
}
witch results in error: invalid initialization of non-const reference of type 'int (&)(int)' from an rvalue of type 'main()::<lambda(int)>'
I tried to add const specified to the type but I don't know where exactly so I tried the following that works with GCC (-std=c++14), however I suspect it is illegal since it fails with clang:
int test(const auto& val) {
return val(2);
}
I know I can use template or function pointers or std::function to achieve the same, then please consider this a didactic question. I want to know what does GCC deduce the type of val to, in the second example above (int test(const auto& val)).
template <typename F>
int test(F val) {
return val(2);
}
int test(int val(int)) {
return val(2);
}
int test(std::function<int(int)> val) {
return val(2);
}
I want to declare a function that takes as argument a function (or lambda) with a specific prototype.
Closures generated by lambda expression have a unique and anonymous type. They could also be generic (i.e. template operator()). There is no "easy" way of declaring a function accepting lambdas with a specific prototype. Your best bet is either using a constrained template parameter with something like std::is_invocable or using some sort of type erasure like function_view.
Note: if your lambda is captureless it is implicitly convertible to a function pointer. E.g.
int test(int (*)(int)) { }
test([](int) -> int {}); // OK
test([i = 0](int) -> int {}); // compile-time error
I want to know what does GCC deduce the type of val to, in the second example.
int test(int val(int))
...is equivalent to...
int test(int (*val)(int))
In fact, having both of them in the same scope results in a redefinition error:
int test(int val(int)) {
return val(2);
}
int test(int (*val)(int)) {
return val(2);
}
prog.cc:5:5: error: redefinition of 'test'
int test(int (*val)(int)) {
^
prog.cc:1:5: note: previous definition is here
int test(int val(int)) {
^

Template inheritance: There are no arguments that depend on a template parameter [duplicate]

This question already has an answer here:
g++ template parameter error
(1 answer)
Closed 6 years ago.
I came across this error when compiling the following code.
After doing some research and reading similar errors in different situations, I came up with the solution I needed.
But I did not fully understood the undelying reason for the error and the fix.
template <typename T>
class TestA {
int a;
T temp;
protected:
int b;
public:
int c;
TestA(T te): a{10}, b{20}, c{30}, temp{te} {}
int geta(){ return a; }
int getb(){ return b; }
int getc(){ return c; }
};
template <typename T>
class TestB {
int atb;
T tempb;
protected:
int btb;
public:
int ctb;
TestB(T te) atb{10}, btb{20}, ctb{30}, tempb{te} {}
};
template <typename T>
class TestInh : public TestA<T>, public TestB<T> {
int aa;
T temptemp;
protected:
int bb;
int b;
public:
int cc;
TestInh(T te) : TestA<T>{te}, TestB<T>{te}, bb{10000}, b{-1000} {}
int get_total() {
// The error happens here!
return geta();
}
};
int main(int argc, char const *argv[]) {
char text = 'a';
TestInh<char> test(text);
//std::cout << test.geta() << std::endl;
std::cout << test.get_total() << std::endl;
//std::cout << test.c << std::endl;
return 0;
}
When compiling this code, I got this error:
testtemplate.cc: In member function ‘int TestInh<T>::get_total()’:
testtemplate.cc:54:32: error: there are no arguments to ‘geta’ that depend on a template parameter, so a declaration of ‘geta’ must be available [-fpermissive]
int get_total() {return geta();}
^
testtemplate.cc:54:32: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
It is solved by calling this->geta() instead of just geta(), but I do not fully understand why this cannot be resolved by the compiler.
Can someone please explain me why?
When extending a class that depends on a template parameter, this kind of become a dependent name.
The problem is that while performing two phase name lookup, the compiler can't know where he can find the function geta. He cannot know it comes from the parent. Because template specialization is a thing, TestA<int> and TestA<double> could be two completely different clas swith different functions and members.
With the this keyword added, the compiler know that geta must be a member function.
Without that, it could be either a member function or non-member function, or a member function of TestB.
Imagine a template code that will either call a function geta from TestA and geta from TestB depending on some template conditions. Ouch. The compiler want to be sure that the code is consistent for every template instantiations.
Another way of saying to the compiler that the function exist as a member function is to add a using statement:
template <typename T>
struct TestInh : TestA<T>, TestB<T> {
// some code...
using TestA<T>::geta;
int get_total() {
// works! With the above using statement,
// the compiler knows that 'geta()' is
// a member function of TestA<T>!
return geta();
}
};