Can one show me an example of ADL without using templates? Never seen something like that. I mean something like here. Specifically I am interested in example in which it leads to some pitfall like in mentioned.
EDIT:
I think Tomalak's answer can be extended to pitfall. Consider this:
namespace dupa {
class A {
};
class B : public A {
public:
int c;
B() {
}
};
void f(B b) {
printf("f from dupa called\n");
}
}
void f(dupa::A) {
printf("f from unnamed namespace called\n");
}
int main()
{
dupa::B b;
f(b);
return 0;
}
Here we expect that f from unnamed namespace will be called, but instead another one is called.
I can't show you something leading to a pitfall, but I can demonstrate ADL working without templates:
namespace foo {
struct T {} lol;
void f(T) {}
}
int main() {
f(foo::lol);
}
Note that lol's type has to be a class-type; I originally tried with a built-in, as you saw, and it didn't work.
The trick to get confusion is creating an scenario where the arguments to the function are interchangeable or convertible and that ADL might pick something that might not be what you would expect. I am not sure if this is impressive or just expected:
namespace a {
struct A {};
void f( A* ) { std::cout << "a::f" << std::endl; }
}
namespace b {
struct B : ::a::A {};
void f( B* ) { std::cout << "b::f" << std::endl; }
}
void test() {
f( new b::B ); // b::f
a::A* p = new b::B;
f( p ); // a::f
}
The types are the same, but ADL will check the static type of the argument and add that namespace into the search. That in turn means that the exact static type might make different functions visible to the compiler. Things can be more confusing when there are more than one argument on which ADL or overload resolution can apply .
No templates.
Using swap() because that is the most common usage.
#include <iostream>
namespace One
{
class A {};
void swap(A& lhs, A& rhs) { std::cout << "Swap-One A\n";}
}
namespace Two
{
class A {};
void swap(A& lhs, A& rhs) { std::cout << "Swap-Two A\n";}
}
int main()
{
One::A oneA_l;
One::A oneA_r;
Two::A twoA_l;
Two::A twoA_r;
swap(oneA_l, oneA_r);
swap(twoA_l, twoA_r);
}
Related
I would like to make an object do something before and after being passed as an argument into a function, but (1) without modifying the function and (2) in a neat way.
Here is the first one that comes to my mind, with RAII.
However, I think the expression (x.lock(), x) is ugly.
I think there would definitely be a good solution, but I can't think of one.
#include <iostream>
using namespace std;
// I can change this class
struct RAII {
RAII() {
cout << "do sth globally" << endl;
}
~RAII() {
cout << "revert it" << endl;
}
};
class A {
public:
// I can change this function, too.
auto lock() {
return RAII();
}
};
void f(const A& obj) {
cout << "a function that I can't change" << endl;
}
int main() {
A x;
// I think the expression is somewhat ugly.
// Can I make this a more neat one-liner, like f(x.locked())?
f((x.lock(), x));
}
The output is the same as below.
do sth globally
a function that I can't change
revert it
You cannot do it when the function and call are:
void f(const A& obj);
f(x);
and you are not allowed to change these. There is no way to make the object aware of a reference being taken.
You can however, call a different function:
void f2(const A& obj) {
obj.before();
f(obj);
obj.after();
}
f2(x); // <- one line
With RAII that would be something along the line of
struct helper {
const A& obj;
helper(const A& obj) : obj(obj) { before(obj); }
~helper() { after(obj); }
};
void f2(const A& a) {
helper h{a};
f(a);
}
Wrapping the function doesn't work for you?
#include <iostream>
class A {
public:
void preProc() const {
std::cout<<"Pre-proc\n";
}
void postProc() const {
std::cout<<"Post-proc\n";
}
};
struct RAII {
explicit RAII(const A& a): a_(a){
a_.preProc();
}
~RAII() {
a_.postProc();
}
private:
const A& a_;
};
void f(const A& a){
}
void fWrap(const A& a){
RAII r(a);
f(a);
}
int main() {
A a;
fWrap(a);
}
Obviously this is just more convenience over just writing a.preProc() and a.postProc() every time before the function call. If it's just a single instance, the entire RAII class can just be removed!
Edit:
My motivation for RAII was perhaps a bit myopic. As #largest_prime_is_463035818 rightly adds, if f() actually threw an exception, the ~RAII() would be called, allowing cleanup of anything that had been set up in the a.preProc() which isn't available in the vanilla function-wrap scenario.
Consider this pseudo-snippet:
class SomeClass
{
public:
SomeClass()
{
if(true)
{
fooCall = [](auto a){ cout << a.sayHello(); };
}
else
{
fooCall = [](auto b){ cout << b.sayHello(); };
}
}
private:
template<typename T>
std::function<void(T)> fooCall;
};
What I want is a class member fooCall which stores a generic lambda, which in turn is assigned in the constructor.
The compiler complains that fooCall cannot be a templated data member.
Is there any simple solution on how i can store generic lambdas in a class?
There is no way you'll be able to choose between two generic lambdas at run-time, as you don't have a concrete signature to type-erase.
If you can make the decision at compile-time, you can templatize the class itself:
template <typename F>
class SomeClass
{
private:
F fooCall;
public:
SomeClass(F&& f) : fooCall{std::move(f)} { }
};
You can then create an helper function to deduce F:
auto makeSomeClassImpl(std::true_type)
{
auto l = [](auto a){ cout << a.sayHello(); };
return SomeClass<decltype(l)>{std::move(l)};
}
auto makeSomeClassImpl(std::false_type)
{
auto l = [](auto b){ cout << b.sayHello(); };
return SomeClass<decltype(l)>{std::move(l)};
}
template <bool B>
auto makeSomeClass()
{
return makeSomeClassImpl(std::bool_constant<B>{});
}
I was not able to store std::function<> as a generic lambda in the class directly as a member. What I was able to do was to specifically use one within the class's constructor. I'm not 100% sure if this is what the OP was trying to achieve but this is what I was able to compile, build & run with what I'm suspecting the OP was aiming for by the code they provided.
template<class>
class test {
public: // While testing I changed this to public access...
// Could not get object below to compile, build & run
/*template<class U = T>
static std::function<void(U)> fooCall;*/
public:
test();
};
template<class T>
test<T>::test() {
// This would not compile, build & run
// fooCall<T> = []( T t ) { std::cout << t.sayHello(); };
// Removed the variable within the class as a member and moved it here
// to local scope of the class's constructor
std::function<void(T)> fooCall = []( auto a ) { std::cout << a.sayHello(); };
T t; // created an instance of <Type T>
fooCall(t); // passed t into fooCall's constructor to invoke the call.
}
struct A {
std::string sayHello() { return "A say's Hello!\n"; }
};
struct B {
std::string sayHello() { return "B say's Hello!\n"; }
};
int main() {
// could not instantiate an object of SomeClass<T> with a member of
// a std::function<> type that is stored by a type of a generic lambda.
/*SomeClass<A> someA;
SomeClass<B> someB;
someA.foo();
someB.foo();*/
// Simply just used the object's constructors to invoke the locally stored lambda within the class's constructor.
test<A> a;
test<B> b;
std::cout << "\nPress any key & enter to quit." << std::endl;
char c;
std::cin >> c;
return 0;
}
With the appropriate headers the above as is should compile, build & run giving the output below (At least in MSVS 2017 on Windows 7 64bit did); I left comments where I ran into errors and tried multiple different techniques to achieve a working example, errors occurred as others suggested and I found even more while working with the above code. What I was able to compile, build and run came down to this simple bit of code here without the comments. I also added another simple class to show it will work with any type:
template<class>
class test {
public:
test();
};
template<class T>
test<T>::test() {
std::function<void( T )> fooCall = []( auto a ) { std::cout << a.sayHello(); };
T t;
fooCall( t );
}
struct A {
std::string sayHello() { return "A say's Hello!\n"; }
};
struct B {
std::string sayHello() { return "B say's Hello!\n"; }
};
struct C {
int sayHello() { return 100; }
};
int main() {
test<A> testA;
test<B> testB;
test<C> testC;
std::cout << "\nPress any key & enter to quit." << std::endl;
char c;
std::cin >> c;
return 0;
}
Output:
A say's Hello!
B say's Hello!
100
Press any key & enter to quit
I don't know if this will help the OP directly or indirectly or not but if it does or even if it doesn't it is still something that they may come back to and build off of.
you can simply use a template class or...
If you can get away with using c++17, you could make fooCall's type std::function<void(const std::any&)> and make a small wrapper for executing it.
method 1 : simply use a template class (C++14).
method 2 : seems to mimic the pseudo code exactly as the OP intended (C++17).
method 3 : is a bit simpler and easier to use than method 2 (C++17).
method 4 : allows us to change the value of fooCall (C++17).
required headers and test structures for the demo :
#include <any> //not required for method 1
#include <string>
#include <utility>
#include <iostream>
#include <functional>
struct typeA {
constexpr const char * sayHello() const { return "Hello from A\n"; }
};
struct typeB {
const std::string sayHello() const { return std::string(std::move("Hello from B\n")); }
};
method 1 :
template <typename T>
class C {
const std::function<void(const T&)> fooCall;
public:
C(): fooCall(std::move([](const T &a) { std::cout << a.sayHello(); })){}
void execFooCall(const T &arg) {
fooCall(arg);
}
};
int main (void) {
typeA A;
typeB B;
C<typeA> c1;
C<typeB> c2;
c1.execFooCall(A);
c2.execFooCall(B);
return 0;
}
method 2 :
bool is_true = true;
class C {
std::function<void(const std::any&)> fooCall;
public:
C() {
if (is_true)
fooCall = [](const std::any &a) { std::cout << std::any_cast<typeA>(a).sayHello(); };
else
fooCall = [](const std::any &a) { std::cout << std::any_cast<typeB>(a).sayHello(); };
}
template <typename T>
void execFooCall(const T &arg) {
fooCall(std::make_any<const T&>(arg));
}
};
int main (void) {
typeA A;
typeB B;
C c1;
is_true = false;
C c2;
c1.execFooCall(A);
c2.execFooCall(B);
return 0;
}
method 3 :
/*Note that this very closely resembles method 1. However, we're going to
build off of this method for method 4 using std::any*/
template <typename T>
class C {
const std::function<void(const std::any&)> fooCall;
public:
C() : fooCall(std::move([](const std::any &a) { std::cout << std::any_cast<T>(a).sayHello(); })) {}
void execFooCall(const T &arg) {
fooCall(std::make_any<const T&>(arg));
}
};
int main (void) {
typeA A;
typeB B;
C<typeA> c1;
C<typeB> c2;
c1.execFooCall(A);
c2.execFooCall(B);
return 0;
}
method 4 :
/*by setting fooCall outside of the constructor we can make C a regular class
instead of a templated one, this also complies with the rule of zero.
Now, we can change the value of fooCall whenever we want.
This will also allow us to do things like create a container that stores
a vector or map of functions that each take different parameter types*/
class C {
std::function<void(const std::any&)> fooCall; //could easily be replaced by a vector or map
public:
/*could easily adapt this to take a function as a parameter so we can change
the entire body of the function*/
template<typename T>
void setFooCall() {
fooCall = [](const std::any &a) { std::cout << std::any_cast<T>(a).sayHello(); };
}
template <typename T>
void execFooCall(const T &arg) {
fooCall(std::make_any<const T&>(arg));
}
};
int main (void) {
typeA A;
typeB B;
C c;
c.setFooCall<typeA>;
c.execFooCall(A);
c.setFooCall<typeB>;
c.execFooCall(B);
return 0;
}
Output from Any method
Hello from A
Hello from B
Here is a problem I stumbled accross when refactoring some code and I was wondering if there is a better way to do it:
#include <iostream>
template<typename T>
class Foo
{
public:
Foo()
{
init(x);
}
T x;
};
void init(int& i)
{
i = 42;
}
int main()
{
Foo<int> foo;
std::cout << foo.x << std::endl;
return 0;
}
Unfortunately, this doesn't compile - neither with GCC or with Clang. The function init called in Foo's constructor is not declared. In this toy example, this could be solved by moving the function itself ahead of the template. However, in a more complex context, this may not work. Originally, I intended to use overloads of init to allow some setup for the classes used in the template.
I assumee that in this context init is a non-dependend name - even though the argument of the function call depends on the template parameter (which was odd for me at first). Is there a way to trick it to also consider function definitions defined after the template itself?
I know that I can use template specialization (which was in the original code in the first place, but I wanted to replace it with simpler overloads):
template<typename>
struct Initializer;
template<>
struct Initializer<int>
{
static void init(int& i)
{
i = 42;
}
}
Is there a way to make this work with function overloads as well? I know, boost::serialization also relies on function overloads for custom types, but I did not really find where and how they implemented that.
You can solve the ordering problem by calling through a template function object - in the same way that boost::hash finds the ADL-function hash_value(x).
This works because the expansion of the template is deferred until the point of first use:
#include <iostream>
namespace A {
struct XX {
friend void init(XX&);
};
}
namespace B {
struct YY {
friend void init(YY&);
};
}
/// default case - call init on T found by ADL
template<class T>
struct call_init
{
void operator()(T& o) const {
init(o);
}
};
template<typename T>
class Foo
{
public:
Foo()
{
auto initialiser = call_init<decltype(this->x)>();
initialiser(this->x);
}
T x;
};
void init(int& x) {
x = 2;
}
// special case, initialise an int
template<> struct call_init<int>
{
void operator()(int& x) const {
init(x);
}
};
int main()
{
Foo<int> foo;
Foo<A::XX> foox;
Foo<B::YY> fooy;
std::cout << foo.x << std::endl;
return 0;
}
Your problem is also that intis not a class and no ADL is done for it, replacing int by custom class works:
template<typename T>
class Foo
{
public:
Foo() { init(x); }
T x;
};
struct C
{
int i = 0;
};
void init(C& c) { c.i = 42; }
Demo.
To allow to works for primitive type as int, you have to introduce some custom type:
template <typename> struct tag {};
template<typename T>
class Foo
{
public:
Foo() { init(x, tag<T>{}); }
T x;
};
void init(int& i, tag<int>) { i = 42; }
Demo
With a normal class. For example:
class A {
public:
int a;
std::string b;
A() {}
~A() {}
}
We can do:
A x;
x.a = 1;
x.b = "hello";
But now I don't want to do like above. I want to access n_index-th attribute of object. For example pseudo like x.get<2>() (or x.set<2>(...)) like x.b.
How can do that? Have any template for that.
Beside if I want code like that
int number = 2;
x.get<number>()
Any problem with constexpr?
I think the closest you can get is using boost::fusion.
An example would be
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/sequence.hpp>
#include <boost/mpl/int.hpp>
#include <iostream>
class A {
public:
int a;
std::string b;
A() {}
~A() {}
};
BOOST_FUSION_ADAPT_STRUCT(A,
(int, a)
(std::string, b)
)
using namespace boost::fusion;
int main()
{
A x;
x.a = 1;
x.b = "hello";
std::cout << at<boost::mpl::int_<0>>(x) << '\n';
std::cout << at<boost::mpl::int_<1>>(x) << '\n';
at<boost::mpl::int_<0>>(x) = 5;
at<boost::mpl::int_<1>>(x) = std::string("World");
std::cout << at<boost::mpl::int_<0>>(x) << '\n';
std::cout << at<boost::mpl::int_<1>>(x) << '\n';
}
If you want to set several values at the same time when you create the object, you could use a multi-parameter constructor. For example, let's imagine you have this:
class A {
public:
int a;
std::string b;
A() {}
~A() {}
};
You could add a constructor that sets a and b:
class A {
public:
int a;
std::string b;
A() {}
A(int a, std::string b) {
this->a = a;
this->b = b;
}
~A() {}
};
That way, you can create your object and set a and b with :
A a = A(1, "hello");
There is no ready-made way of setting the n-th attribute of your object. You could make one, but I would very, very highly recommend that you don't. Like I said above, if you reorder your attributes, then you will have to rework everything.
If you really, really want to make your life very, very, very much harder, a very ugly and error-prone way of doing this would be like :
template<class T>
void A::setNth(int nth, const T& value) {
switch (nth) {
case 1: a = value; break;
case 2: b = value; break;
// You should #include <stdexcept> to use runtime_error, or you could handle the exception in some other way.
default: throw std::runtime_error("A::setNthAttribute : Value of nth is out of bounds.");
}
}
For the getter:
template<class T>
void A::getNth(int nth, T& valueOut) {
switch (nth) {
case 1: valueOut = a; break;
case 2: valueOut = b; break;
default: throw std::runtime_error("A::getNthAttribute : Value of nth is out of bounds.");
}
}
You would use these methods like this:
A a;
a.setNth(1, 2); // put 2 into a
int i;
a.getNth(1, i); // put a into i
Just writing this code send shivers down my spine. Please, never write what I just wrote. Chuck Norris will kill yoU agfh
86sd asdsa dDASD8!4.
What you are considering is in fact possible, but a bit of a headache. I would approach it by creating a template getter and setter for every member that one can set or get, and then having a template method that takes an int and sets or gets the appropriate property. The getters/setters would have to be specialized for the correct type, and throw an error for other types. This method would have to use a switch to return the right member:
class bar {
private:
int a;
std::string b;
template<T>
T getA() {
// error
}
template<T>
T getB() {
// error
}
template<T>
void setA(const T& A) {
// error
}
template<T>
void setB(const T& B) {
// error
}
template <> std::string getB(); // specialization
template <> int getA();
template <> void setB(const std::string&);
template <> void setA(int);
public:
template<T>
T get(int what) {
switch(what) {
case 1:
return getA();
case 2:
return getB();
default:
// handle error here
break;
}
}
template<T>
void set(int what, const T& t) {
switch(what) {
case 1:
return setA<T>(t);
case 2:
return setB<T>(t);
default:
// handle error here
break;
}
}
};
bar b;
b.set<std::string>(2, "foo");
auto str = b.get<std::string>(2);
Here's an elaborate way to accomplish what you want.
#include <iostream>
#include <string>
// A namespace explicitly defined for class A.
namespace A_NS
{
// A template for members of A.
template <int> struct Member;
// Specialization for the first member.
template <> struct Member<1>
{
using type = int;
type var;
};
// Specialization for the second member.
template <> struct Member<2>
{
using type = std::string;
type var;
};
}
class A {
public:
A() {}
~A() {}
template <int N> typename A_NS::Member<N>::type get() const
{
return static_cast<A_NS::Member<N> const&>(members).var;
}
template <int N> void set(typename A_NS::Member<N>::type const& in)
{
static_cast<A_NS::Member<N>&>(members).var = in;
}
private:
// Define a type for the member variables.
struct Members : A_NS::Member<1>, A_NS::Member<2> {};
// The member variables.
Members members;
};
int main()
{
A a;
a.set<1>(10);
a.set<2>("test");
std::cout << a.get<1>() << ", " << a.get<2>() << std::endl;
}
Output:
10, test
Suppose we need to instantiate a function that calls some class method from inside non-trivial code.
#include <iostream>
class A
{
public:
int f() { return 1; }
int g() { return 2; }
};
template <class T, int (T::*method)()>
int func(T& x)
{
// some complex code here calling method()
return (x.*method)();
}
int main()
{
A a;
std::cout << func<A, &A::f>(a) << "\n"
<< func<A, &A::g>(a) << "\n";
return 0;
}
This code compiles and works fine. Now suppose that the two methods are actually const and non-const, like this:
class A
{
int val_;
public:
A() : val_(0) {}
int alloc() { return ++val_; }
int get() const { return val_; }
};
This time we can't use the same approach, because the member functions have different signatures due to const qualifier. Moving the problem to run time does not seem to solve anything, Is there a way to avoid rewriting func() as two functions in this situation?
Can you change passing method from template parameter to function parameter?
If yes, this works:
#include <iostream>
class A
{
public:
int f() { return 1; }
int g() const { return 2; }
};
template <class T, class F>
int func(F method, T& x)
{
// some complex code here calling method()
return (x.*method)();
}
int main()
{
A a;
std::cout << func(&A::f, a) << "\n"
<< func(&A::g, a) << "\n";
return 0;
}