Can I use a function object without instantiation? - c++

Having the following code:
template<typename T, typename OutStream = std::ostream> struct print {
OutStream &operator()(T const &toPrint, OutStream &outStream = std::cout) const {
outStream << toPrint;
return outStream;
}
};
This call is erroneous:
print<int>(2);
Error message:
1>main.cpp(38): error C2440: '<function-style-cast>' : cannot convert from 'int' to 'print<T>'
1> with
1> [
1> T=int
1> ]
1> No constructor could take the source type, or constructor overload resolution was ambiguous
This call is not erroneous:
print<int> intPrinter;
intPrinter(2);
Can I use a function object somehow without its instantiation?
I cannot use a template function here, because I need partial specialization capabilities.

I think that you want to say
print<int>()(2);
Here, the first parens create a temporary print<int> object by calling the (zero-argument) constructor, then the second parens actually invoke the function call operator on that object. The error you're getting now is caused by the fact that
print<int>(2);
Is interpreted as a typecast expression to convert 2 into a print<int>, which isn't what you want (and also isn't legal).
Hope this helps!

For those stateless wrapper classes, it might be better to use static member functions:
template<typename T, typename OutStream = std::ostream>
struct printer
{
static OutStream & print()(T const &toPrint, OutStream &outStream = std::cout)
{
outStream << toPrint;
return outStream;
}
};
Then you can invoke them with printer<Foo>::print(x);, and you can typically supply a type-deducing helper function template:
template <typename T> std::ostream & print(T const & x)
{
return printer<T, std::ostream>::print(x);
}
Now you can just say print(x);.

Related

Using std::mem_fn, generate wrapper object for Overloaded functions [duplicate]

When compiling the following code, Visual Studio reports:
\main.cpp(21): error C2664: 'std::_Call_wrapper<std::_Callable_pmd<int ClassA::* const ,_Arg0,false>,false> std::mem_fn<void,ClassA>(int ClassA::* const )' : cannot convert argument 1 from 'overloaded-function' to 'int ClassA::* const '
1> with
1> [
1> _Arg0=ClassA
1> ]
1> Context does not allow for disambiguation of overloaded function
Why is the compiler confused when creating mem_fptr1? But some how mem_fptr2 is ok when I specify the types.
Can I create member function pointer to an overloaded member function that takes no argument?
class ClassA
{
public:
void memberfunction()
{
std::cout <<"Invoking ClassA::memberfunction without argument" << std::endl;
}
void memberfunction(int arg)
{
std::cout << "Invoking ClassA::memberfunction with integer " << arg << std::endl;
}
};
int main()
{
auto mem_fptr1 = std::mem_fn<void, ClassA>(&ClassA::memberfunction);
auto mem_fptr2 = std::mem_fn<void, ClassA, int>(&ClassA::memberfunction);
mem_fptr1(ClassA());
mem_fptr2(ClassA(), 3);
}
The template overloads taking a variadic list of argument types were introduced in C++11 but removed in C++14 as defect #2048. The way to specify a particular overload is to specify a function type as the first template argument (the second template argument, the class type, can be omitted as it can be deduced):
auto mem_fptr1 = std::mem_fn<void()>(&ClassA::memberfunction);
auto mem_fptr2 = std::mem_fn<void(int)>(&ClassA::memberfunction);
The function type R is then composed with the class type T as R T::* to give the member function type. This also allows forming a std::mem_fn to a data member (where R is a non-function type).
Note that your code (for mem_fptr2) does not work in C++14 where the template overloads taking a variadic list of argument types are removed; the above code will work in both versions of the Standard.
An alternative is to perform a member function cast; in this case you do not need to specify template arguments to mem_fn:
auto mem_fptr1 = std::mem_fn(
static_cast<void (ClassA::*)()>(&ClassA::memberfunction));
auto mem_fptr2 = std::mem_fn(
static_cast<void (ClassA::*)(int)>(&ClassA::memberfunction));

Syntax to pass argument to unordered_set hash function in c++

I have created a hasher class for a custom type I'm using, but it has a constructor that takes an argument. I can't figure out the syntax to use this in an unordered_set.
class Hasher {
unsigned arg;
public:
Hasher(unsigned a) : arg(a) {}
size_t operator()(const MyType& t) const {
return calculate_hash(arg, t);
}
}
int main() {
unordered_set<MyType, Hasher(2)> myset; // compilation error
}
The error message:
In file included from Tetrahedron.cc:5:
./Triangulation.h:52:29: error: template argument for template type parameter must be a type
unordered_set<TetraFace,FaceHasher(2)> faces2;
^~~~~~~~~~~~~
/bin/../lib/gcc/x86_64-redhat-linux/6.3.1/../../../../include/c++/6.3.1/bits/unordered_set.h:90:11: note: template parameter is declared here
class _Hash = hash<_Value>,
^
I also tried
unordered_set<MyType, Hasher> myset(Hasher(2));
but I still get an error:
In file included from Tetrahedron.cc:5:
./Triangulation.h:52:59: error: expected ')'
unordered_set<TetraFace,FaceHasher> faces2(FaceHasher(2));
^
./Triangulation.h:52:58: note: to match this '('
unordered_set<TetraFace,FaceHasher> faces2(FaceHasher(2));
^
You're getting a compile error there because you're trying to pass an object (i.e. instance) of type Hasher as a template argument.
Like your error describes: template argument for template type parameter must be a type
It's expecting a type, and you're passing in a value.
Parameterize the arg at the type level.
template<unsigned A>
class Hasher {
unsigned arg = A;
public:
size_t operator()(const int& t) const {
std::cout << arg << std::endl;
return 0;
}
};
int main() {
std::unordered_set<int, Hasher<2>> myset;
myset.insert(5); // prints 2
std::unordered_set<int, Hasher<3>> myset2;
myset2.insert(3); // prints 3
}
Unfortunately it is not possible to construct a std::unorderd_set with just the hash object. All of the constructors that take the hash object have a parameter before it for bucket_count. You would need to specify the value for it like
unordered_set<MyType, Hasher> myset(some_bucket_count_value, Hasher(2));
If you do not want to do that then you have to make Hasher default constructable.
Also not that
return calculate_hash(arg);
Is not going to work as you will always hash arg no matter what MyType you pass. You need to be hashing the MyType object for the std::unordered_set to really work.

Is it possible to get a template to use a class and a member function of that class?

I'm trying to make a for_each function for a generic object that uses an size function and an item index function. But I'm having some difficulty with the syntax.
This is what I have so far (starting at line 128):
class base1
{
protected:
std::vector<int> items;
public:
base1()
: items({1,2,3})
{
}
int GetCount() const
{
}
};
class base2 : public base1
{
public:
base2()
: base1()
{
}
int GetItem(int i) const
{
return items[i];
}
};
class derived : public base2
{
public:
derived()
: base2()
{
}
};
template <typename CONTAINER, typename CONTAINER_BASE1, typename CONTAINER_BASE2, typename SIZE, typename CONTAINED, typename FUNC>
void for_each(CONTAINER* container, SIZE (CONTAINER_BASE1::*GetSize)() const, CONTAINED (CONTAINER_BASE2::*GetItem)(SIZE) const, FUNC& body)
{
for (SIZE i = 0; i < container->*GetSize(); ++i)
{
body(container->*GetItem(i));
}
}
void fn()
{
derived x;
for_each(&x, &derived::GetCount, &derived::GetItem, [](int i){
++i;
});
}
Right now, I get an error from VC++ 2013 stating:
1>d:\projects\test\test.cpp(169): error C2064: term does not evaluate to a function taking 0 arguments
1> d:\projects\test\test.cpp(180) : see reference to function template instantiation 'void for_each<derived,base1,base2,int,int,fn::<lambda_862ea397905775f7e094cde6fe9b462c>>(CONTAINER *,SIZE (__thiscall base1::* )(void) const,CONTAINED (__thiscall base2::* )(SIZE) const,FUNC &)' being compiled
1> with
1> [
1> CONTAINER=derived
1> , SIZE=int
1> , CONTAINED=int
1> , FUNC=fn::<lambda_862ea397905775f7e094cde6fe9b462c>
1> ]
1>d:\projects\test\test.cpp(171): error C2064: term does not evaluate to a function taking 1 arguments
Any ideas as to what the problem is?
You have two bugs. You take the functor by non-const lvalue reference - FUNC& body - which doesn't bind to a temporary like a lambda; this was hidden by a terrible MSVC extension that allows such bindings. You should accept the function object by value (the way it is usually done by the standard library), by const lvalue reference (if copying is expensive and/or identity is important), or by forwarding reference (if identity is important and operator() can be non-const).
Second is operator precedence. The postfix function call operator has higher precedence than .* and ->*. container->*GetSize() is container->*(GetSize()); you want (container->*GetSize)().
I'm also not sure about this design. It's probably better to provide a uniform interface, and simply do, e.g., container.size() and container.at(i) than using this tortured system of pointer-to-member-functions.

g++ compiler error: couldn't deduce template parameter ‘_Funct’

I'm trying to use an ANSI C++ for_each statement to iterate over and print the elements of a standard vector. It works if I have the for_each call a non-overloaded function, but yields a compiler error if I have it call an overloaded function.
Here's a minimal test program to show where the compiler error occurs:
#include <algorithm>
#include <iostream>
#include <vector>
struct S {
char c;
int i;
};
std::vector<S> v;
void print_struct(int idx);
void print_struct(const struct S& s);
// f: a non-overloaded version of the preceding function.
void f(const struct S& s);
int main()
{
v.push_back((struct S){'a', 1});
v.push_back((struct S){'b', 2});
v.push_back((struct S){'c', 3});
for (unsigned int i = 0; i < v.size(); ++i)
print_struct(i);
/* ERROR! */
std::for_each(v.begin(), v.end(), print_struct);
/* WORKAROUND: */
std::for_each(v.begin(), v.end(), f);
return 0;
}
// print_struct: Print a struct by its index in vector v.
void print_struct(int idx)
{
std::cout << v[idx].c << ',' << v[idx].i << '\n';
}
// print_struct: Print a struct by reference.
void print_struct(const struct S& s)
{
std::cout << s.c << ',' << s.i << '\n';
}
// f: a non-overloaded version of the preceding function.
void f(const struct S& s)
{
std::cout << s.c << ',' << s.i << '\n';
}
I compiled this in openSUSE 12.2 using:
g++-4.7 -ansi -Wall for_each.cpp -o for_each
The full error message is:
for_each.cpp: In function ‘int main()’:
for_each.cpp:31:48: error: no matching function for call to ‘for_each(std::vector<S>::iterator, std::vector<S>::iterator, <unresolved overloaded function type>)’
for_each.cpp:31:48: note: candidate is:
In file included from /usr/include/c++/4.7/algorithm:63:0,
from for_each.cpp:5:
/usr/include/c++/4.7/bits/stl_algo.h:4436:5: note: template<class _IIter, class _Funct> _Funct std::for_each(_IIter, _IIter, _Funct)
/usr/include/c++/4.7/bits/stl_algo.h:4436:5: note: template argument deduction/substitution failed:
for_each.cpp:31:48: note: couldn't deduce template parameter ‘_Funct’
I don't see any search results for this particular error on Stack Overflow, or on the web generally. Any help would be appreciated.
A names refers to an overload set. You'll need to specify which overload you want:
std::for_each(v.begin(), v.end(), (void (&)(S const&)) print_struct);
Another approach is to use a polymorphic callable function object as a helper:
struct PrintStruct
{
template <typename T> void operator()(T const& v) const
{ return print_struct(v); }
};
int main()
{
PrintStruct helper;
std::vector<S> sv;
std::vector<int> iv;
// helper works for both:
std::for_each(sv.begin(), sv.end(), helper);
std::for_each(iv.begin(), iv.end(), helper);
std::for_each declaration looks like this:
template<class InputIter, class Func>
void for_each(InputIter first, InputIter last, Func func);
As you can see, it takes anything you give it as the third parameter. There is no restriction that it has to be a callable type of a certain signature or a callable type at all.
When dealing with overloaded functions, they're inherently ambiguous unless you give them some context to select the right one. In a call to an overloaded function, this context are the arguments you pass. When you need a pointer, however, you can't use arguments as a context, and the for_each parameter also doesn't count as a context, since it takes anything.
As an example of where a function parameter can be a valid context to select the right overload, see this:
// our overloads
void f(int){}
void f(double){}
typedef void (*funcptr_type)(int);
void g(funcptr_type){}
// ...
g(&f); // will select 'void f(int)' overload, since that's
// the only valid one given 'g's parameter
As you can see, you give a clear context here that helps the compiler select the right overload and not have it ambiguous. std::for_each's parameters do not give such a context, since they take anything.
There are two solutions:
manually provide the context either by
casting to the right function pointer type, or
using an intermediate variable of the right type and passing that
use a non-overloaded function that dispatches to an overloaded one (as you did with f)
Note that in C++11, you could also use a lambda for the second option:
std::for_each(v.begin(), v.end(), [](const S& s){ print_struct(s); });
Some notes on your code:
(struct S){'a', 1} is a compound literal and not standard C++
you don't need struct S in C++, only S suffices

How to use template type argument in lambda?

Is it possible to use a template type argument from a surrounding template function within a local anonymous function? I'm pretty certain I can't declare a template lambda ...
For example how would I go about doing something like this:
template <typename T>
void TrimString(std::basic_string<T>& str, const std::locale& loc = std::locale())
{
// std::isspace as lambda unary predicate?
auto fn = [&loc](T c){ return std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space, c); };
// trim right
str.erase(std::find_if(str.rbegin(), str.rend(), std::not1(fn)).base(), str.end());
// trim left
str.erase(str.begin(), std::find_if(str.begin(), str.end(), std::not1(fn)));
}
Currently this generates the following error:
error C2039: 'argument_type' : is not a member of '`anonymous-namespace'::<lambda0>'
Which makes sense as the lambda has no clue about argument T from the surrounding template function.
I use VS2010 and gcc 4.7 but I don't want to use boost.
Any ideas?
Edit: It appears I was wrong in my assumption that the problem was the template argument itself. Rather it is the use of std::not1 being compiled with the lambda function. Here is the more verbose error output:
error C2039: 'argument_type' : is not a member of '`anonymous-namespace'::<lambda0>'
: see declaration of '`anonymous-namespace'::<lambda0>'
: see reference to class template instantiation 'std::unary_negate<_Fn1>' being compiled
with
[
_Fn1=`anonymous-namespace'::<lambda0>
]
: see reference to function template instantiation 'void TrimString<char>(std::basic_string<_Elem,_Traits,_Ax> &,const std::locale &)' being compiled
with
[
_Elem=char,
_Traits=std::char_traits<char>,
_Ax=std::allocator<char>
]
Do you need to explicitly declare the type for the argument if it's a function type? I'm not sure what I'm doing wrong still ...
Answers:
Option 1: If I don't use std::not1 and instead negate the returned value in the lambda I get the same behavior without issue.
auto fn = [&loc](T c){ return !std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space, c); };
Option 2: Since the lambda is not longer equivalent to how std::isspace would behave as a unary predicate a function object constructor cast also does the trick.
str.erase(std::find_if(str.rbegin(), str.rend(), std::not1(std::function<bool(T)>(fn))).base(), str.end());
The problem is not caused by using a template parameter inside the lambda, as the parameter has already been resolved to a type at the time when the lambda is constructed.
The problem is that the lambda you define cannot be combined with std::not1, which requires, as argument, a std::unary_function<argument_type,return_type>.
The easiest way to solve the problem is to not use std::not1, and instead negate the predication right in the lambda expression:
auto fn = [&loc](T c){ return !std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space,c); };
The complete code that compiles and works with GCC 4.7.0 then becomes:
#include <string>
#include <algorithm>
#include <locale>
#include <iostream>
template <typename T>
void TrimString(std::basic_string<T>& str, const std::locale& loc = std::locale())
{
auto fn = [&loc](T c){ return !std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space,c); };
str.erase(std::find_if(str.rbegin(), str.rend(),fn).base(), str.end());
str.erase(str.begin(), std::find_if(str.begin(), str.end(), fn));
}
int main() {
std::basic_string<char> s(" hello ");
TrimString(s);
std::cout << s << std::endl;
return 0;
}
This outputs
hello
as expected.
You most certainly can use T as parameter type of a lambda expression. The following program compile fines on GCC 4.5.1 :
include <iostream>
template<typename T>
void f(T arg)
{
auto print = [](T a) { std::cout << a << std::endl; };
print(arg);
}
int main() {
f(8899);
f("Nawaz");
return 0;
}
See yourself : http://ideone.com/l32Z6
BTW, the error message seems to indicate that the problem lies somewhere else, specifically with a lambda declared at namespace scope:
error C2039: 'argument_type' : is not a member of '`anonymous-namespace'::<lambda0>'
After your EDIT, all I can say is that dont use std::not1 then. In fact, you don't even need it. You could use return !whatever-expression in the lambda itself.
Edit: As #Nawaz points out, your error must be coming form somewhere else ... what I describe below is overkill ...
Using decltype, you could do something like the following:
template <typename T>
void TrimString(std::basic_string<T>& str,
const std::locale& loc = std::locale(),
T arg = T())
{
auto fn = [&loc](decltype(arg) c){ return std::use_facet<std::ctype<T>>(loc).is(std::ctype_base::space, c); };
//...rest of your code
}
This is using (or abusing) the fact that the expression decltype(arg) evaluates to the type of arg, which in this case is the type of T.