Candidate template ignored: couldn't infer template argument 'T' - c++

I know this question probably has been asked before but I'm a beginner to templates, and here is my code,
HeaderFile.h
class Identity {
public:
template <typename T>
T getFamilyMembers() {
if(1) {
return false;
}
std::string whatever = "Test";
return whatever;
}
};
Main.cpp
#include "HeaderFile.h"
int main() {
Identity id;
std::cout << id.getFamilyMembers() << "\n";
}
Compiler issue two errors,
Main.cpp:25:10: error: no matching member function for call to 'getFamilyMembers'
id.getFamilyMembers();
~~~^~~~~~~~~~
HeaderFile.h:22:11: note: candidate template ignored: couldn't infer template argument 'T'
T getFamilyMembers() {

This isn't how templates work.
The caller specifies what T is. When T is a return type, then all return statements in the function must be a T value, or something implicitly convertible to T. The function itself can't dictate what T is at runtime.
Beyond that, T is known at compile time. You can't return different types in different situations without the help of a variant type like std::variant.
For each distinct T, a totally new version of the function is created. Template functions, therefore, are used when a generic algorithm can be applied to multiple types. For example, a naive implementation of a "swap two values" algorithm might copy one of the values to a temporary variable:
void swap(int & a, int & b) {
int temp = a;
a = b;
b = temp;
}
But now we have to write a new swap() function for each possible type of thing we ever want to swap! Enter templates: we write the function once, as a template:
template <typename T>
void swap(T & a, T & b) {
T temp = a;
a = b;
b = temp;
}
Now the compiler will do the work for us, creating new versions of swap() whenever it sees a T that it hasn't before.
In your particular case, if you want to return a value that might be a string but might be nothing, that's what std::optional is for. In this case, you could return an std::optional<std::string>. You could also just return std::string and use an empty string to notate that there are no family members.
Given that the name of the function implies that multiple items could be returned, it might make more sense to have the function return std::vector<std::string> and then the "no family members" case is simply represented as an empty vector.

Related

Lambda as template function

I have a very strange problem. To keep things simple, lets say I want to have a function which takes 2 functions with the same declaration as arguments
template<typename Func>
void foo(Func a, Func b)
{
std::cout << "good";
}
To try things out I took putchar from cstdio, and created an identical function to match the putchar.
int myPutcharFunc(int)
{
return 0;
}
int main()
{
auto myPutcharLambda = [](int) -> int
{
return 0;
};
foo(putchar, myPutcharFunc); // okay
foo(putchar, myPutcharLambda); //deduced conflicting types for parameter 'Func' ('int (__attribute__((__cdecl__)) *)(int)' and 'main()::<lambda(int)>')
}
Now, the lambda does not want to compile (the key is I want to use lambda capture).
So lets add template specialization, because the programmer is wiser than the machine, right? :)
template<typename Func>
void foo(Func a, Func b)
{
std::cout << "good";
}
template<>
void foo(int(*)(int), int(*)(int))
{
std::cout << "good";
}
No luck, the same error - why?
But for some reason, when I comment out the template specialization:
//template<>
void foo(int(*)(int), int(*)(int))
{
std::cout << "good";
}
The code compiles. I obviously do not want to overload foo for EVERY set of function's arguments - thats what templates are for. Every step was tested both with msvc++ and g++. What am I doing wrong?
Two possibilities.
1: Just put + in front of the lambda:
foo(putchar, +myPutcharLambda);
That works because unary + expects an integer-like value, such as a pointer. Therefore, the lambda converts to a function pointer.
Ultimately a (non-capturing) lambda doesn't have the same type as a function pointer, even though it's willing to convert to a function pointer.
How is a compiler supposed to know which conversions are allowed to make two objects of the same type?
2: There is another option, making use of the fact that the ?: is willing to do some conversions, converting one type to another in some circumstances.
template<typename Func1, typename Func2>
void foo2(Func1 a, Func2 b)
{
using common_type = decltype(true?a:b); // or 'false', it doesn't matter
foo<common_type>(a,b);
}
Every lambda is a different type, so you'll need to have two different template parameters to get them
template<typename FuncA, typename FuncB>
void foo(FuncA a, FuncB b)
Types don't decay when deducing template types (SEE COMMENT FOR CORRECTION). So a lambda remains a lambda and doesn't decay to a function pointer. Same reason a string literal is deduced as a char[N] instead of a const char *.
With your second example using specialization, it doesn't want to use your specialization, since the lambda is not a function pointer. You can cast the Lambda to a function pointer and make it work: https://godbolt.org/g/ISgPci The trick you can do here is say +my_lambda because + is defined for pointers so it will force the non-capturing lambda to become a function pointer.
A lambda has its own type which can decay to a function pointer but not in the case of a template function match, it will for the real function as you found because of the implicit conversion.
In the case of matching to a template you need to disambiguate and explicitly instantiate foo with the type you want or convert the lambda to a function pointer.
foo<decltype(putchar)>(putchar, myPutcharLambda);
or
foo(putchar, +myPutcharLambda);

Compiler error trying to delete template type which is a pointer

I'm new to C++ and I have the ambition to understand how templates work. So I have implemented a generic list MyList which may contain both built-in primitive types and pointers. In the remove function I want to distinguish pointer types and built-ins so I can delete the object behind the pointer but leave the built-ins untouched.
To distinguish the template types, which can be pointers or non-pointers, I wrote the following functions, which work fine:
// distinguish between pointer and non-pointer type of template variable
template<typename T> bool is_pointer(T t) {
return false;
}
template<typename T> bool is_pointer(T* t) {
return true;
}
In the list function remove the idea was to test for pointers and delete them in case. However, the delete statement does not compile:
template<typename T> void MyList<T>::remove() {
...
if (is_pointer(temp->getContent())) {
// delete object pointer points to
T t = temp->getContent();
cout << t; // prints out address
// delete t; // produces compiler error (see below)
}
In the main.cpp I test the list class with various types, I call amongst others:
MyList<int> mylist; // with type int
mylist.remove();
mylist.add(3);
// add and remove elements
MyList<string> mylist2; // with type string
...
MyList<string*> mylist3; // with type string*
mylist.add(new string("three"));
mylist.remove();
When I comment out the statement delete t; I can verify that the control flow is correct: the if-statement is only entered for the string* example. However, if I uncomment the delete statement the compiler complains like that:
../mylist.h: In member function ‘void MyList<T>::remove() [with T = int]’:
../main.cpp:36:18: instantiated from here
../mylist.h:124:6: error: type ‘int’ argument given to ‘delete’, expected pointer
../mylist.h: In member function ‘void MyList<T>::remove() [with T = std::basic_string<char>]’:
../main.cpp:71:18: instantiated from here
../mylist.h:124:6: error: type ‘struct std::basic_string<char>’ argument given to ‘delete’, expected pointer
make: *** [main.o] Error 1
What is it that I don't see? I'm using the delete statement on pointers only but still I get these compiler errors. If I print out t in the if-statement it is a pointer address!
A template is a blueprint that the compiler uses to actually create types based on the use of the blueprint. When you use you template with int and string* the compiler will actually create two variations of MyList, replacing T with the actual type. The implementation that uses int for T is bogus, because deleting an int does not make sense. The actual code the compiler generates is
int t = temp->getContent();
cout << t;
delete t;
This is incorrect, as you could figure out.
If you instantiate the template with T = int, you get:
void MyList::remove() {
if (false) {
T t = temp->getContent();
cout << t;
delete t;
}
}
Even if the code block is never executed, it must be syntactically correct.
I suggest to use C++ 11 type_traits and auto_ptr like this
#include <type_traits>
template<typename T> void MyList<T>::remove() {
...
if (is_pointer(T)) {
// delete object pointer points to
T t = temp->getContent();
cout << t; // prints out address
auto_ptr tempobj(T);
}
Also look at this Determine if Type is a pointer in a template function that could be useful incase your compiler is not C++ 11 compliant.
Thanks
Niraj Rathi

How does overloading function call work in C++?

I read that function call () can also be overloaded. http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
What would the following mean?
It works.
template<typename T, typename Comp>
struct bind{
T v;
Comp comp;
bool operator()(const T& b){
return comp(b,v);
}
};
int main(){
bind<int, less<int> > b;
b.v = 2;
cout << b(3) << "\n";
}
It means that if you create an object of type bind<>, you can apply the function-call operator to that object.
Like this:
bind<int, std::less<int>> b;
b.v = 2;
std::cout << b(1) << "\n";
That snippet might print "true" on the standard output.
If you have a class called foo, I'm sure you understand what it means to call a member function of an object of that type:
foo f;
f.bar();
You may also understand that you can overload certain operations. For example, you could overload operator+ for foo so that you could do something like this:
foo f, g;
f + g;
Now you can also overload operator() for a class, which allows you to call it as though it were a function:
foo f;
f();
Yes, f is not a function but it is an object of class type that overloads operator(). Class types that do this are known as functors or function objects.
In the example you've given, bind is a functor. When you create an object of that type, you can call it like a function, passing it a const T& and it will return a bool back to you. The implementation of operator() actually calls the function stored in comp, passing it both the T object you passed to operator(), a, and the member object v of type T.
As it stands, it doesn't mean much of anything except "syntax error". For example:
template<T, Op>
This simply isn't allowed. For each template parameter, you need to specify whether it's a type (using class or typename) or a non-type parameter such as an int. Since the apparent intent is that both these should be type parameters, you need something like:
template <class T, class Op>
or:
template <typename T, typename Op>
For this situation, there's no difference in meaning between class and typename.
struct bind{
T v;
Leaving v uninitialized will lead to undefined behavior, so you probably don't want to allow that. You'd normally prevent it by adding a constructor that takes a T as its parameter and initializes v to that value:
bind(T const &v) : v(v) {}
When you include a constructor like this, the compiler won't automatically generate a default constructor, so it's no longer possible to create a bind object with v uninitialized -- exactly what we wanted.
Although creating the comp object:
Op comp;
is fairly harmless, it's also quite unnecessary. You could just as well do the comparison with a temporary instance created with Op(), in which case this:
bool operator()(const T& a){
return comp(a,v);
}
...would become something like this (and the Op comp; simply removed):
bool operator()(T const &a) {
return Op()(a, v);
}
Even with the corrections, I'd consider this code obsolescent. In C++98/03, it would have been useful in a situation where you needed to supply a functor to an algorithm, such as:
std::remove_copy_if(a.begin(), a.end(), bind<int,
std::back_inserter(b),
bind<int, std::less<int> >(5));
...which would copy numbers from a to b, removing those less that 5.
In C++11, however, most (if not all) uses of this bind should probably be written as lambdas instead though, so the bit above would become something like:
std::remove_copy_if(a.begin(), a.end(), bind<int,
std::back_inserter(b),
[](int x) { return x < 5; });
This is not only shorter, but (at least once you're used to it) quite a bit simpler than using std::less and bind to put together a function. It won't generally make any difference in run-time efficiency -- a lambda is basically a "shorthand" way of generating a class template, so what it generates would end up pretty similar to the code using bind.

Templates instantiation in C++

I am confused by how C++ instantiate template. I have a piece of code:
template <class T, int arraySize>
void test1(T (&array)[arraySize])
{
cout << typeid(T).name() << endl;
}
template<class T>
void test2(T &array)
{
cout << typeid(T).name() << endl;
}
int main()
{
int abc[5];
test1(abc);
test2(abc);
return 0;
}
Here are my questions:
1. How does the size of array abc is passed to test1 (the parameter arraySize )?
2. How does C++ compiler determine the type of T in the two templates?
There is no parameter passing in the normal sense, since template parameters are resolved at compile time.
Both arraySize and T are inferred from the type of the array parameter. Since you pass an int[5], arraySize and T become 5 and int, respectively, at compile time.
If, for example, you declared int* abc = new int[5];, your compiler would barf at the point you try to call test1(abc). Apart from a basic type-mismatch, int* doesn't carry enough information to infer the size of the array.
It is called template argument deduction.
The type of abc at call-site is : int(&)[5] which has two info combined: int and 5. And the function template accepts argument of type T(&)[N], but the argument at call-site is, int(&)[5], so the compiler deduces that T is int and N is 5.
Read these:
The C++ Template Argument Deduction (at ACCU)
Template argument deduction (C++ only) (at IBM)
In test1 the compiler creates a template with T[arraySize] being its form.
When you call test1(abc) you are providing an input argument of type int[5] which the template matcher automatically matches.
However, if you were to write
int n=10;
int *abc = new int[n];
test1(abc);
test1<int,n>(abc);
then the compilation would fail and the compiler would claim that it has no template matching the test1(abc) function call or the test1< int,n >(abc) function call.
This is because the size of abc is now dynamically allocated and so the type of abc is a pointer which has a different type and hence no template could be matched to the above two calls.
The following code shows you some types
#include <iostream>
using namespace std;
template <class T> void printName() {cout<<typeid(T).name()<<endl;}
int main()
{
printName<int[2]>(); //type = A2_i
printName<int*>(); //type = Pi
getchar();
return 0;
}
I'd also add to what Nawaz says: the theory is type inference.

c++ deduction of "non type pointer to function" class template parameters

Consider a template class like:
template<typename ReturnType, ReturnType Fn()>
class Proxy
{
void run()
{
ReturnType ret = Fn();
// ... do something ...
}
};
// and a functions
int fn1() { return 5; }
float fn2() { return 5; }
This can be instantiated by using:
Proxy<int, &fn1> p1;
But explicitly declaring the return value type seems needless. What I am trying to achieve is something like:
someProxyInstantation<&fn1> p1;
someProxyInstantation<&fn2> p2;
Unfortunately, I'm no c++ expect and this seems like a hidden corner of the language (at least for me).
If I could just get from the pointer to the function to its type - something like:
std::tr1::result_of<&fn>::type // Error 1 error C2923: 'std::tr1::result_of' : 'fn1' is not a valid template type argument for parameter '_Fty'
the error makes sense since the parameter is not a "type" at all
C++0x has the decltype(&fn1) but that is years away.
Any way of doing this in C++03 (+ tr1)?
Restrictions:
- I don't want to pass the functor, f1 and f2 have to remain global functions that have a return value (can't move it to parameter).)
This isn't possible in C++03. If you want to pass a function pointer as a non-type parameter, the compiler has to know the type of the parameter. So you have to provide the missing pieces (in this case, the return type). You can give the proxy the function pointer as a value at runtime, and provide it with the type of it as the only argument. Then you could write a generator function for you that does this job:
template<typename T>
Proxy<T> make_proxy(T t) { return Proxy<T>(t); }
Sadly, in current C++, you still have to give it the type in order to assign to a automatic variable:
Proxy<int(*)()> p = make_proxy(&fn1);
You can't use auto p = make_proxy(&fn1); yet. Note that if you want to use a function type on the left side, you have to change the generator function to provide not a function pointer type:
template<typename T>
Proxy<typename boost::remove_pointer<T>::type> make_proxy(T t) {
return Proxy<typename boost::remove_pointer<T>::type>(t);
}
Now you can do
Proxy<int()> p = make_proxy(&fn1);
using the proxy, you can now just do
doSomething(make_proxy(&fn1));
And if doSomething is templated or otherwise polymorphic, it will not require you to know the exact type of the function.