#include "stdafx.h"
#include <iostream>
using namespace std;
template<class Type>
struct X
{
void run()const
{//Why on earth this doesn't work?
[&]()
{
Type::alloc();
};
}
void run_1()const
{//if this does
Type::alloc();
}
};
struct T
{
static void alloc()
{}
};
int _tmain(int argc, _TCHAR* argv[])
{
X<T> x;
x.run_1();
return 0;
}
AFAIC lambda is a unnamed fnc, so if that's true why run doesn't compile and run_1 does?
Using VS2010 sp beta1.
You'll have to pass it in to the lambda:
void run()const
{//Why on earth this doesn't work?
auto alloc = Type::alloc;
[&]()
{
alloc();
};
}
I have to admit I am not quite sure, but I think is only a VS 2010 limitation and it should compile fine in C++0x (cf. templates, typename, lambda -> dependent names not dependent?). I think the mechanics of what you see are like following:
When defining template, types defined by template parameters are not "fully fledged" typenames in some aspects. One example demonstrating this is that while someone might expect X<Foo>::Type (with X from your example) to return Foo, it does not.
You have to call the lambda. It is a functor so you need a () at the end of it to effectively call the lambda.
/* Code does NOT answer question above...
void run()const
{//Why on earth this doesn't work?
[&]()
{
Type::alloc();
}(); //very important parenthesis if you wish to call the lambda
}*/
I seem to have misread the question. Sorry.
But there is already a similar post on SO Template type is not "seen" by the compiler inside a lambda
And here is another link that refers to the same problem, with a quote from the standard about this.
templates, typename, lambda -> dependent names not dependent?
Related
I'm trying to build a class made up by a vector of threads.
The class should have a method that take as argument another function, this function has to be executed by a new threads.
I would like to avoid use of native pointer, so I'm not excatly sure how to build this specific method.
You can pass a function like this:
template <typename F>
void call_function(F f) {
f();
}
For example:
#include <iostream>
void sayHello() {
std::cout << "Hello\n";
}
int main() {
call_function(sayHello);
}
regarding your constraints I suggest to use std::function. You can then use std::bind and if using C++20, std::bind_front.
cheers,
FM.
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 9 years ago.
#include <iostream>
namespace oo{
class A{
public:
template<typename T>
static T get_value(){return static_cast<T>(55);}
};
template <typename T=A>
class B{
public:
static double f(){return T::get_value<double>();}
};
}
int main(int argc, char *argv[])
{
using std::cout;
using std::endl;
cout << oo::B<oo::A>::f() << endl;
return 0;
}
Considering the example up here, it compiles with an error "type name is not allowed" which refers to "double" and arguments in "get_value()".
Someone has righted this wrong by rewriting the function f() as followed:
static double f(){return T::template get_value<double>(); }
Yet, I do not quite understand the use of "template" here. Could anyone explain that to me, please?
Thanks in advance for your comments.
The reason is how the compiler interpret that line, when you use templates, the syntax has more than one possible interpretation, take a look to the following :
static double f()
{
return T::get_value < double > ();
}
in your function, how you now that the T parameter passed to the B class has a function named get_value or a data member named get_value ? If the case is the second then you are using the operator lees-than between that member and double, and then between double and (). Well the first assumption of the compiler is these option, if you wat to tell him that this is a function with template (for the correct interpretation of "<") you need to put the keyword template
this is what's going on at runtime.
namespace oo{
class A{
public:
// template<typename T> // T replaced with <double> type.
static double get_value(){return static_cast<double>(55);}
};
//template <typename T=A> // T replaced with <oo::A> type.
class B{
public:
static double f(){return oo::A::get_value/*<double>*/();}
};
}
int main(int argc, char *argv[])
{
using std::cout;
using std::endl;
cout << oo::B::f() << endl;
return 0;
}
this line :
static double f(){return T::get_value();}
is correct and usually will be compiled without any errors(depend on witch compiler you're using), because the template declaration will be valid for the next scope.
template <class T>
class foo
{
//T will be valid in this scope.
};
this is not the case to implement template classes/functions, you usually want to do that in cases where you want to prevent the using of multiple overloading.
This question already has answers here:
How do I assign an alias to a function name in C++?
(8 answers)
Closed 2 years ago.
If I have a class Foo in namespace bar:
namespace bar
{
class Foo { ... }
};
I can then:
using Baz = bar::Foo;
and now it is just like I defined the class in my namespace with the name Baz.
Is it possible to do the same for functions?
namespace bar
{
void f();
}
And then:
using g = bar::f; // error: ‘f’ in namespace ‘bar’ does not name a type
What is the cleanest way to do this?
The solution should also hold for template functions.
Definition: If some entity B is an alias of A, than if any or all usages (not declarations or definitions of course) of A are replaced by B in the source code than the (stripped) generated code remains the same. For example typedef A B is an alias. #define B A is an alias (at least). T& B = A is not an alias, B can effectively implemented as an indirect pointer, wheres an "unaliased" A can use "immediate semantics".
You can define a function alias (with some work) using perfect forwarding:
template <typename... Args>
auto g(Args&&... args) -> decltype(f(std::forward<Args>(args)...)) {
return f(std::forward<Args>(args)...);
}
This solution does apply even if f is overloaded and/or a function template.
The constexpr function pointer can be used as a function alias.
namespace bar
{
int f();
}
constexpr auto g = bar::f;
It is highly likely (but not guaranteed by the language) that using g uses bar::f directly.
Specifically, this depends on compiler version and optimization level.
In particular, this is the case for:
GCC 4.7.1+, without optimization,
Clang 3.1+, without optimization,
MSVC 19.14+, with optimization.
See assembly generated by these compilers.
Classes are types, so they can be aliased with typedef and using (in C++11).
Functions are much more like objects, so there's no mechanism to alias them. At best you could use function pointers or function references:
void (*g)() = &bar::f;
void (&h)() = bar::f;
g();
h();
In the same vein, there's no mechanism for aliasing variables (short of through pointers or references).
It's possible to introduce the function into a different scope without changing its name. That means that you can alias a function with a different qualified name:
namespace bar {
void f();
}
namespace baz {
using bar::f;
}
void foo() {
baz::f();
}
Absolutely:
#include <iostream>
namespace Bar
{
void test()
{
std::cout << "Test\n";
}
template<typename T>
void test2(T const& a)
{
std::cout << "Test: " << a << std::endl;
}
}
void (&alias)() = Bar::test;
void (&a2)(int const&) = Bar::test2<int>;
int main()
{
Bar::test();
alias();
a2(3);
}
Try:
> g++ a.cpp
> ./a.out
Test
Test
Test: 3
>
A reference is an alias to an existing object.
I just created a reference to a function. The reference can be used in exactly the same way as the original object.
It's not standard C++, but most compilers provide a way of doing this. With GCC you can do this:
void f () __attribute__ ((weak, alias ("__f")));
This creates the symbol f as an alias for __f. With VC++ you do the same thing this way:
#pragma comment(linker, "/export:f=__f")
You can use good old macros
namespace bar
{
void f();
}
#define f bar::f
int main()
{
f();
}
typedef boost::function<void (int,bool)> MyCallback;
void RegisterCallback(MyCallback callback);
class A {
public:
void GoodCallback(int intArg,bool boolArg) {
printf("calling GoodCallback (%d,%s)\n",intArg,boolArg?"true":"false");
}
void BadCallback(int intArg) {
printf("calling BadCallback (%d)\n",intArg);
}
};
int TestFunction() {
A * myA=new A();
RegisterCallback(boost::bind(&A::GoodCallback,myA,_1,_2));
RegisterCallback(boost::bind(&A::BadCallback,myA,_1));
return 0;
}
Is there any way that I can make the second call to RegisterCallback not compile?
For context:
I recently changed the callback signature and added the bool argument. I thought I had updated everything that was using this, but I was mistaken. Other than renaming RegisterCallback everytime I change the signature, I would like to have a way to have the compiler enforce that all arguments are used.
The documentation says
Any extra arguments are silently ignored
It has to be this way in order to support _N placeholders. Witness:
void foo (int a, const char* b) {
std::cout << "called foo(" << a << "," << b << ")" << std::endl;
}
int main () {
boost::bind(foo,_1, _2)(1, "abc", foo, main, 2.0);
boost::bind(foo,_2, _5)(3.0, 2, foo, main, "def");
}
prints
called foo(1,abc)
called foo(2,def)
Any combination of arguments in the beginning, in the end or in the middle of the argument list can be ignored.
You need a simpler binder that doesn't support anything like _N placeholders. Boost doesn't seem to have one.
The problem isn't boost::function; the problem is that the function object boost::bind returns will take anything as parameters. Bind is, more or less, runtime defined, not compile-time defined. Therefore, the boost::bind object can be used with any boost::function.
[edit] OK, apparently boost::function is also a problem. But it's not the only problem.
You could always use std::function<...> instead.
The following does not compile on VS2010 SP1:
#include <functional>
void foo();
void bar(int);
int main()
{
std::function<void ()> f= std::bind(foo);
std::function<void ()> g= std::bind(bar); // does not match signature, does not compile.
return 0;
}
I'm a bit late with this answer but since the problem is the binding you could do this step later with the help of a templated version for your callback registration function and another one for regular function pointers:
template<typename C>
void RegisterCallback(void (C::* func)(int, bool), C* inst)
{
MyCallback callback(boost::bind(func, inst, _1,_2));
}
void RegisterCallback(void (*func)(int, bool))
{
MyCallback callback(func);
}
A * myA = new A();
RegisterCallback(&A::GoodCallback, myA);
RegisterCallback(&A::BadCallback, myA); // DOES NOT COMPILE
RegisterCallback(GoodCallback);
RegisterCallback(BadCallback); // DOES NOT COMPILE
This works as expected in VS2010 but has the disavantage of needing not one but two callback registration functions to correctly deal with member and non-member functions.
As another option you might have a look at the boost function_types library. It provides a parameter_types metafunction that extracts the parameter types of function pointers and returns them as a MPL sequence. Then with a bit template magic it's possible to validate the parameters of the callback function, something like:
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/mpl/equal.hpp>
using namespace boost;
using namespace boost::function_types;
template< typename Function >
void RegisterCallback(Function f)
{
BOOST_MPL_ASSERT((
mpl::equal<
parameter_types< Function >,
parameter_types< void(int,bool) >
>
));
MyCallback callback(f);
}
template<typename Function, typename T>
void RegisterCallback(Function f, T* inst)
{
BOOST_MPL_ASSERT((
mpl::equal<
parameter_types< Function >,
parameter_types< void (T::*)(int,bool) >
>
));
MyCallback callback(boost::bind(f, inst, _1, _2));
}
This also works as expected in VS2010 but you still need two function declarations although it should be possible to pack them in one if you define them inside a struct (and use a default template parameter argument for T);
I have some (library API, so I can't change the function prototype) function which is written the following way:
void FreeContext(Context c);
Now, at some moment of my execution I have Context* local_context; variable and this is also not a subject to change.
I wish to use boost::bind with FreeContext function, but I need to retrieve Context from local variable Context*.
If I write my code the following way, the compiler says it's "illegal indirection":
boost::bind(::FreeContext, *_1);
I managed to solve this problem the following way:
template <typename T> T retranslate_parameter(T* t) {
return *t;
}
boost::bind(::FreeContext,
boost::bind(retranslate_parameter<Context>, _1));
But this solution doesn't seem really good to me. Any ideas on how to solve this using something like *_1. Maybe writing a small lambda function?
You could use Boost.Lambda which have overloaded the * operator for _n.
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <algorithm>
#include <cstdio>
typedef int Context;
void FreeContext(Context c) {
printf("%d\n", c);
}
int main() {
using boost::lambda::bind;
using boost::lambda::_1;
Context x = 5;
Context y = 6;
Context* p[] = {&x, &y};
std::for_each(p, p+2, bind(FreeContext, *_1));
return 0;
}
Use either Boost.Lambda or Boost.Phoenix to have a working operator* on a placeholder.
You can also place the Context pointer in a shared_ptr with a custom deleter:
#include <memory> // shared_ptr
typedef int Context;
void FreeContext(Context c)
{
printf("%d\n", c);
}
int main()
{
Context x = 5;
Context* local_context = &x;
std::shared_ptr<Context> context(local_context,
[](Context* c) { FreeContext(*c); });
}
Not sure this is relevant though. Good luck!