can std::forward takes std::function<void()> as the class type? - c++11

I've always seen std::forward being utilized as below, utilized inside a template function
template<class T>
void foo(T&& arg): bar(std::forward<T>(arg)){}
Suppose I want to do this.
class A
{
private:
std::function<void()> bar;
public:
template<class T>
A(T&& arg):
bar(std::forward<T>(arg))
{}
};
Since bar already has its type defined. I can also directly specify T as std::function<void()> >.
class A
{
private:
std::function<void()> bar;
public:
A(std::function<void()>&& arg):
bar(std::forward<std::function<void()>>(arg))
{}
};
Both would be ok to compile. However, the second realization only support A(const std::function<void()>). While the first realization support A(const std::function<void()>&) and A(std::function<void()>&&) etc.

Forward is a conditional move of its argument. It is almost equivalent to std::move if and only if the type passed to it is a value type or rvalue reference type.
A move is a cast to an rvalue reference.
If you pass a different type to std::forward than its argument type, it will do horrible things. If convertible between, this would often involve creating a temporary within a function then returning a reference to it.
The proper thing to pass to std::forward(x) is X, where the type of x is X&&. Anything else is going to be extremely quirky and advanced use, and will probably cause unexpected behavior...
In your case, the second works fine, but is pointless. As std::forward is a conditional move, and we are passing it a fixed type, we know it is a std::move.
So we should replace std::forward<std::function<void()>>(arg) with std::move(arg), which is both clearer and more conventional. Also, equivalent in this case.
Generally std::forward should only be used in cases where you are using forwarding references.

Related

Remove class member type part from decltype

I ran into I case I had not seen before, while using decltype on a member of a templated class. I wanted to make a nicer make_unique so that changing type on the member does not cause fixing the make_unique calls. I wanted to avoid this using decltype(member)::element_type as the type for make_unique but got an error. Here is a simple snippet that shows the error (and I understand why it is shown):
#include <memory>
template<typename T>
struct foo
{
foo()
{
// g++ gives:
// dependent-name 'decltype (((foo<T>*)this)->foo<T>::p_)::element_type' is parsed as a non-type, but instantiation yields a type
// say 'typename decltype (((foo<T>*)this)->foo<T>::p_)::element_type' if a type is meant
//
// How can I atleast remove the class name from the type?
p_ = std::make_unique<decltype(p_)::element_type>();
// g++ gives:
// dependent-name 'decltype (p)::element_type' is parsed as a non-type, but instantiation yields a type
// say 'typename decltype (p)::element_type' if a type is meant
//
// makes sense since p here is dependent on T
std::unique_ptr<T> p = std::make_unique<decltype(p)::element_type>();
// This one is fine, makes sense, since the type is known
std::unique_ptr<int> p2 = std::make_unique<decltype(p2)::element_type>();
}
std::unique_ptr<T> p_;
};
int main()
{
foo<int> f;
return 0;
}
My question is, is there a nice/pretty way to remove the 'is a member of' ((foo<T>*)this)->foo<T>::p_))part from the decltype value, so that at least I could use the same fix and simply provide typename on the member variable p_ ? The long fix suggested by g++ seems kind of ugly.
5 minutes after posting I had an idea that I could do
p_ = std::make_unique<decltype(std::remove_reference(*p_)::type)>();
but that seems to give a parse error.
You can simply place a typename before decltype().
I mean
p_ = std::make_unique<typename decltype(p_)::element_type>();

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)

static_assert with partial template specialization

template<typename T, typename U = void>
struct S { /* static_assert(0, "type unsupported"); */ };
template<typename T>
struct S<T, typename std::enable_if<std::is_integral<T>::value, void>::type> {
void foo() {}
};
...
S<int> i;
i.foo();
S<double> d;
// d.foo();
I would be expecting that the "master template" would never be instantiated for the case of int, but if I uncomment the static_assert, the S<int> instantiation will fail. Even a lone typedef S<int> Si; would fail to compile. (GCC 4.9.2 Cygwin)
What I aimed to achieve is not for S<double> to fail at the foo() call, but at the instantiation of the template itself, and that with a meaningful error message. I'm aware I can do something like typename T::nonexistent_type t; in the master template which will prevent the template for compiling, but that'd be inferior to a static_assert message. (Note: putting the static_assert within a function definition in the master template still fails compilation for S<int>)
Why does the static_assert fail even though that template is not instantiated? Is this mandated (or perhaps "unspecified") by the standard? Is there a way to fail with a static_assert the way I wish to?
The expression in the static_assert must be dependent on a template parameter if you wish it to be instantiation-time only. This is guaranteed by Standard- the implementation may (but has no obligation to) check static_assertions in templates that are not dependent on any template parameter.
Your code is a strange roundabout way of doing something like
template<typename T> struct S {
static_assert(std::is_integral<T>::value, "type unsupported");
void foo() {}
};
This clearly communicates to the compiler the dependency between the expression and the template parameter, and is far clearer and easier to read as well. I actually couldn't quite figure out if you wanted compilation to fail for integral types or for non-integral types.

Correct way of initializing a unique_ptr

Working on learning how to use smart pointers and C++ in general... Assume that I have the following class:
template<typename T>
class MyClass {
public:
MyClass(const T& def_val)
private:
std::unique_ptr<T> default_val;
};
What is the idiomatic way of implementing the constructor if I would only like to store a pointer to an object of type T with the value given in the default_val class member? My understanding is also that I don't have to define a destructor at all, since the unique_ptr will automatically taking care of cleaning up itself?
The way you have written your code, MyClass can only store a unique pointer to a copy of the constructor parameter:
MyClass::MyClass(const T& def_val)
: default_val(new T(def_val))
{
}
This means that T must be copy constructible.
My understanding is also that I don't have to define a destructor at all, since the unique_ptr will automatically taking care of cleaning up itself?
Correct. That is 1 of 2 main purposes for unique_ptr, the 2nd being the guarantee that it has only one owner.
If you're using C++11 you could add also a constructor that accepts an rvalue ref
template<typename T>
class MyClass {
public:
MyClass(T&& def_val) : default_val(new T(std::move(def_val))) {}
MyClass::MyClass(const T& def_val) : default_val(new T(def_val)) {}
private:
std::unique_ptr<T> default_val;
};
now you accept both const ref, generating a copy, or temporaries

boost::variant and operator<< overloading

I wanted to test a simple thing like the following:
#include <iostream>
#include <boost/variant.hpp>
template<typename T1,typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1,T2>& dt){
os << dt.first << dt.second;
return os;
}
int main(){
boost::variant<int, std::pair<int,int>, bool> v;
v = std::pair<int,int>(3,3);
std::cout << v << std::endl;
}
This should actually work, because for normal types, like int, double and so on, it compiles.
boost::variant has a printer vistor which it uses internally to output the content to the stream.
Actually this fails to compile, but I do not really know the problem:
The codes fails here: in variant_io.hpp
template <typename OStream>
class printer
: public boost::static_visitor<>
{
private: // representation
OStream& out_;
public: // structors
explicit printer(OStream& out)
: out_( out )
{
}
public: // visitor interface
template <typename T>
void operator()(const T& operand) const
{
out_ << operand; // HEEEEEEERRRRREE!!!!!!!!!!!!
}
private:
printer& operator=(const printer&);
};
With the message:
/usr/local/include/boost/variant/detail/variant_io.hpp|64|error: cannot bind 'std::basic_ostream<char>' lvalue to 'std::basic_ostream<char>&&'
Does someone know what I did wrong, and why?
Thanks a lot!
Most likely it's not finding your overload of operator <<, and then gets confused trying to match some other overload, leading to whatever message you're getting.
What you did wrong: You overloaded the stream operator in the global namespace instead of the namespace the right-hand-side class is defined in, so it's not found by ADL.
Trying to overload the stream operator for a standard class is a doomed exercise in the first place, unfortunately. You can't actually do that. I'm not sure if there is an explicit rule against it. However, if you place the operator in namespace std as you have to in order to make it properly findable by ADL, you violate the rule that you can't add your own stuff to namespace std except in very specific cases, this not being one of them.
The bottom line is that std::pair doesn't have a stream operator, and it's not possible to legally add a generic one that is useful. You can add one for a specific instantiation, if one of the parameters is a class you defined yourself; in this case the operator needs to be placed next to your own class.
Overloaded operator<< must be findable by argument dependent lookup. That means you have to put it in associated namespace of one of the arguments.
The first argument has only one associated namespace, std. The second also has only one associated namespace, std. However it is only permitted to overload symbols in std for user-defined types. Since std::pair<int, int> is not user-defined type, this is not allowed. However it is allowed for a structure or class you define yourself. Obviously in that case it is easier to place the overload to your namespace, not std.
That said if you put that overload in namespace std, it will actually work.
Also note, that boost::tuple does have operator<< (in separate header that you have to include, but it does), so you can use that instead.

Resources