Undefined reference to friend function template defined inside class in a namespace - c++11

This is a follow-up on my answer to this question.
The original answer I posted does not have any namespaces, and it solves the problem. However, the OP subsequently made an edit claiming that the solution does not work if the class is inside a namespace.
My initial reaction was that you can make it work by simply having using N::f; either at global scope or inside main() (or any other function). While that is certainly the case, the OP (justifiably) commented that this is not ideal, and I agree.
Nevertheless, I still thought that calling N::f without having using N::f; should work just fine, but to my surprise I got an undefined reference error when I tried the following:
#include<iostream>
namespace N
{
template<class T>
class Class;
template<typename U, typename W>
Class<W> f (Class<U>& C, const Class<U>& D);
template<class T>
class Class
{
protected: // this could be private
T m_t;
public:
Class()
:
m_t(T())
{}
Class(T t)
:
m_t(t)
{}
T& getT()
{
return m_t;
}
template<typename U, typename W>
friend Class<W> f (Class<T>& C, const Class<T>& D)
{
C.m_t += D.m_t;
Class<W> R;
std::cout << R.m_t << std::endl; // I don't want this to be possible
return R;
}
};
}
int main()
{
N::Class<int> C(42), D(24);
std::cout << N::f<int, char>(C, D).getT() << std::endl;
}
error: undefined reference to N::Class<char> N::f<int, char>(N::Class<int>&, N::Class<int> const&)'.
At this point, I went on to try different compiler versions and discovered that the above works as it does without a namespace with GCC < 6 but not with GCC > 6. ICC 17 also seems to pick up on the protected member access inside f, but not ICC 18. Clang never picks it up.
Which is the intended behaviour? Should the definition be made available to the linker in this case without using N::f;?.
Edit 1:
To clarify, I want to retain the intended behaviour, namely restricting f to be a friend only to Class instantiations that match its arguments (so in the example f would be friend to Class<T> but not to Class<W>).

Related

Using variadic templates and move semantics

I am trying to wrap my head around variadic templates,
move semantics, (maybe perfect forwarding?),
and learn how to pass variable down to different functions.
Lets say, there is a class Foo which holds an array of Elem (templated) class instances.
These array elements regularly gets re-initialized (hence the Elem.init function).
Below I am trying to initialize an Elem with three large strings (or any other large objects which implements move semantics) to exactly the place where they will be stored:
In the Foo's array, at a certain location.
Is that even possible to move them to the Foo's vector location right away?
Or will it be always a "copy semantics" instead of a move.
Overall, I am trying to avoid copying large stack allocated strings around and somehow have them be in the target vector's location.
Not sure what would be the best way to do that.
(All i got is a segmentation fault at the moment)
Thank you for reading!
Code below online: https://onlinegdb.com/HJc7U_jIO
#include <iostream>
#include <vector>
#include <string>
class Elem
{
public:
void init(std::string&& s1, std::string&& s2, std::string&& s3)
{
s1 = std::move(s1);
s2 = std::move(s2);
s3 = std::move(s3);
std::cout << mS1 << mS2 << mS3;
}
private:
std::string mS1;
std::string mS2;
std::string mS3;
};
template <class T>
class Foo
{
public:
template <typename... Args>
void add(Args... args)
{
mElements[mNextFreeIndex].init(args...);
mNextFreeIndex++;
}
private:
std::vector<T> mElements;
int mNextFreeIndex;
};
int main()
{
Foo<Elem> foo;
foo.add(std::move("Apple"), std::move("Pear"), std::move("Carrot")); //passing 3 parameters
return 0;
}
To properly "debug" these issues, you may want to write a class with copy & move constructors, destructor and copy & move assignment operators which declare their being executed. Then you can tell what happens with the values as they get passed around and/or created.
Anyway, you're calling the add() method with three std::string&& arguments. But - inside the function, once they are bound to args..., they are now lvalues! You either need to use std::move() in your add() method:
template <typename... Args>
void add(Args... args)
{
mElements[mNextFreeIndex].init(std::move(args)...);
mNextFreeIndex++;
}
or apply forwarding:
template <typename... Args>
void add(Args&&... args)
{
mElements[mNextFreeIndex].init(std::forward<Args>(args)...);
mNextFreeIndex++;
}
On a mostly unrelated note, I would recommend reading this: "Parameter" vs "Argument" regarding the use of these two terms.

C++ Check if generic object has member function matching signature

first post, so hopefully not violating any etiquette. Feel free to give suggestions for making the question better.
I've seen a few posts similar to this one: Check if a class has a member function of a given signature, but none do quite what I want. Sure it "works with polymorphism" in the sense that it can properly check subclass types for the function that comes from a superclass, but what I'd like to do is check the object itself and not the class. Using some (slightly tweaked) code from that post:
// Somewhere in back-end
#include <type_traits>
template<typename, typename T>
struct HasFunction {
static_assert(integral_constant<T, false>::value,
"Second template parameter needs to be of function type."
);
};
template<typename C, typename Ret, typename... Args>
class HasFunction<C, Ret(Args...)> {
template<typename T>
static constexpr auto check(T*) -> typename is_same<
decltype(declval<T>().myfunc(declval<Args>()...)), Ret>::type;
template<typename>
static constexpr false_type check(...);
typedef decltype(check<C>(0)) type;
public:
static constexpr bool value = type::value;
};
struct W {};
struct X : W { int myfunc(double) { return 42; } };
struct Y : X {};
I'd like to have something like the following:
// somewhere else in back-end. Called by client code and doesn't know
// what it's been passed!
template <class T>
void DoSomething(T& obj) {
if (HasFunction<T, int(double)>::value)
cout << "Found it!" << endl;
// Do something with obj.myfunc
else cout << "Nothin to see here" << endl;
}
int main()
{
Y y;
W* w = &y; // same object
DoSomething(y); // Found it!
DoSomething(*w); // Nothin to see here?
}
The problem is that the same object being viewed polymorphically causes different results (because the deduced type is what is being checked and not the object). So for example, if I was iterating over a collection of W*'s and calling DoSomething I would want it to no-op on W's but it should do something for X's and Y's. Is this achievable? I'm still digging into templates so I'm still not quite sure what's possible but it seems like it isn't. Is there a different way of doing it altogether?
Also, slightly less related to that specific problem: Is there a way to make HasFunction more like an interface so I could arbitrarily check for different functions? i.e. not have ".myfunc" concrete within it? (seems like it's only possible with macros?) e.g.
template<typename T>
struct HasFoo<T> : HasFunction<T, int foo(void)> {};
int main() {
Bar b;
if(HasFoo<b>::value) b.foo();
}
Obviously that's invalid syntax but hopefully it gets the point across.
It's just not possible to perform deep inspection on a base class pointer in order to check for possible member functions on the pointed-to type (for derived types that are not known ahead of time). Even if we get reflection.
The C++ standard provides us no way to perform this kind of inspection, because the kind of run time type information that is guaranteed to be available is very limited, basically relegated to the type_info structure.
Your compiler/platform may provide additional run-time type information that you can hook into, although the exact types and machinery used to provide RTTI are generally undocumented and difficult to examine (This article by Quarkslab attempts to inspect MSVC's RTTI hierarchy)

Passing an unspecialised template to another template

Given the following code here in IDEOne:
#include <iostream>
#include <vector>
#include <list>
template<typename T>
class MyVectorCollection
{
using collection = std::vector<T>;
};
template<typename C, typename T>
class MyGenericCollection
{
using collection = C;
};
template<typename C, typename T>
class MyMoreGenericCollection
{
using collection = C<T>;
};
int main() {
// your code goes here
MyVectorCollection<int> a;
MyGenericCollection<std::list<int>, int> b;
MyMoreGenericCollection<std::list, int> c; // How to do this?
return 0;
}
I get the error:
prog.cpp:20:24: error: ‘C’ is not a template
using collection = C<T>;
^
prog.cpp: In function ‘int main()’:
prog.cpp:27:43: error: type/value mismatch at argument 1 in template parameter list for ‘template<class C, class T> class MyMoreGenericCollection’
MyMoreGenericCollection<std::list, int> c;
^
prog.cpp:27:43: note: expected a type, got ‘list’
How can I write my code such that I can use a C<T> at compile time without having an explicit list of potential specialisations, and avoiding macros, if possible? I realise std::list isn't a typename, but I don't know how to progress, and I have been unable to find a similar question here.
(Note that this is just an MCVE, my actual usage is much more involved.)
Just to tidy up, here is the solution. The search term I was looking for is template template, and whilst I did find a possible duplicate, I think this question and answer is much simpler to follow.
So, thanks to the hint from #Some programmer dude, I looked up template template and updated the code to this, which does compile:
template<template<typename, typename> class C, typename T>
class MyMoreGenericCollection
{
using collection = C<T, std::allocator<T>>;
};
We declare the first template parameter as a template itself, and remembering that the standard library constructors take two parameters, we need to make the inner template take two parameters. There is (as far as I am aware) no way to automatically use the default second parameter, so for the sake of this example I explicitly state the default.
I could of course add a third parameter to the master template that could be used to specify the allocator, which itself would also be a template, but I leave that as an exercise for th reader.

When initializing an atomic class member it requires a 'deleted' function, but adding it would make it no longer trivially copyable

When initializing an atomic class member it requires a 'deleted' function, but adding it would make it no longer trivially copyable which is a requirement for an object/struct to be atomic. Am I just not understanding how to do this correctly, or is this a problem in the c++ standard?
Take the example below:
#include <atomic>
#include <cstdint>
template<typename T>
struct A
{
T * data;
std::atomic<uintptr_t> next;
};
template<typename T>
class B
{
std::atomic<A<T>> myA;
public:
B ( A<T> & a ) noexcept
{
myA.store(a, std::memory_order_relaxed );
}
};
int main ()
{
A<int> a;
B<int> b(a);
return 0;
}
Trying to compile this with g++ gives error: use of deleted function 'A<int>::A(const A<int>&)' myA.store(a, std::memory_order_relaxed);. My understanding of this error is that the atomic::store method is looking for that constructor in my struct A but not finding it.
Now here is what happens when I add that constructor:
#include <atomic>
#include <cstdint>
template<typename T>
struct A
{
T * data;
std::atomic<uintptr_t> next;
A(const A<T>& obj) { }
A( ) { }
};
template<typename T>
class B
{
std::atomic<A<T>> myA;
public:
B ( A<T> & a ) noexcept
{
myA.store(a, std::memory_order_relaxed );
}
};
int main ()
{
A<int> a;
B<int> b(a);
return 0;
}
I no longer receive the above compiler error but a new one coming from the requirements of the atomic class required from 'class B<int>' .... error: static assertion failed: std::atomic requires a trivially copyable type ... In other words by adding the used-defined constructors I have made my struct A a non-trivially copyable object which cannot be initialized in class B. However, without the user-defined constructors I cannot use the store method in myA.store(a, std::memory_order_relaxed).
This seems like a flaw in the design of the std::atomic class. Now maybe I am just doing something wrong because I don't have a lot of experience using C++11 and up (I'm old school). Since 11 there have been a lot of changes and the requirements seem to be a lot stricter. I'm hoping someone can tell me how to achieve what I want to achieve.
Also I cannot change std::atomic<A<T>> myA; to std::atomic<A<T>> * myA; (changed to pointer) or std::atomic<A<T>*> myA;. I realize this will compile but it will destroy the fundamental design of a class I am trying to build.
The problem here resides in the fact that std::atomic requires a trivially copiable type. This because trivially copyable types are the only sure types in C++ which can be directly copied by copying their memory contents directly (eg. through std::memcpy). Also non-formerly trivially copyable types could be safe to raw copy but no assumption can be made on this.
This is indeed important for std::atomic since copy on temporary values is made through std::memcpy, see some implementation details for Clang for example.
Now at the same time std::atomic is not copy constructible, and this is for reasonable reasons, check this answer for example, so it's implicitly not trivially copyable (nor any type which contains them).
If, absurdly, you would allow a std::atomic to contain another std::atomic, and the implementation of std::atomic contains a lock, how would you manage copying it atomically? How should it work?

How to store functional objects with different signatures in modern C++

I would like to know if there is a way to store functional objects (functions, callbacks, ...) with different signatures in a standard container (std::map) with modern C++ only. The library that manages the container does not know which signatures will be used by its "clients".
My need is the same as exposed here : How to store functional objects with different signatures in a container?, and this solution https://stackoverflow.com/a/8304873/4042960 is about perfect for me: I would just like to do the same thing without boost. As far as I know, there is no std::any. The best solution for me would be to store std::function without specialized them, but I do not know how to do it, if it is possible.
Edit:
With the answers you give to me I wrote this example :
#include <map>
#include <memory>
#include <functional>
#include <string>
#include <iostream>
#include <stdexcept>
class FunctionMap
{
struct Base {
virtual ~Base() {}
};
template<class R, class... Args>
struct Func : Base
{
std::function<R(Args...)> f;
};
std::map<std::string, std::shared_ptr<Base> > _map;
public:
template<class R, class... Args>
void store(const std::string &key, const std::function<R(Args...)> &f) {
auto pfunc = std::make_shared<Func<R, Args...> >();
pfunc->f = f;
_map.insert(std::make_pair(key, pfunc));
}
template<class R, class... Args>
std::function<R(Args...)> get(const std::string &key) {
auto pfunc = std::dynamic_pointer_cast<Func<R, Args...> >(_map[key]);
if (pfunc)
return pfunc->f;
else
throw std::runtime_error("Bad type for function's parameters");
}
};
// test
int plus(int a, int b) { return a+b; }
double multiplies(double x, double y) { return x*y; }
int main()
{
FunctionMap fm;
fm.store("plus", std::function<int(int, int)>(&plus));
fm.store("multiplies", std::function<double(double, double)>(&multiplies));
// fm.store("square", std::bind(&multiplies, std::placeholders::_1, std::placeholders::_1));
std::cout << "5 + 3 = " << fm.get<int, int, int>("plus")(5, 3) << std::endl;
std::cout << "5 * 3 = " << fm.get<double, double, double>("multiplies")(5.0, 3.0) << std::endl;
return 0;
}
This works well, but I would like to improve it a bit:
1) I would like to be able to use std::bind : fm.store("square", std::bind(&multiplies, std::placeholders::_1, std::placeholders::_1)); but currently that does not compile ;
2) I would like to use fm.get<int (int, int)>("plus") instead of fm.get<int, int, int>("plus") but I do not know how to do it.
Many thanks for your help !
You can write your own any. Without all the compiler workarounds and stuff, boost::any can be written in about 30 lines of code.
Function objects are in no way different from any other kind of objects, so anything applicable to objects in general is applicable to function objects.
So you want to store different kinds of (function) objects in a map. This is normally done by storing (smart) pointers to a base class, where each derived class holds its own kind of objects you want to store.
struct Base {
virtual ~Base(){}
};
template <typename A>
struct Object : Base {
A value;
};
That's your basic caveman's boost::any. Your clients do something like this:
Base* b = mymap["foo"];
dynamic_cast<Object<void(*)(int)>*>(b)->val(123);
But with appropriate checks of course.

Resources