Unexpected nullptr in expansion of variadic template constructor - c++

Difficult to explain, here a short stand-alone example of what I mean:
#include <functional>
#include <iostream>
typedef std::function<void(void)> f_t;
struct A { A(f_t f) { f(); } };
struct B { B(f_t f) { f(); } };
struct C { C(f_t f) { f(); } };
template<typename ... TT>
struct T : TT...
{
T( ) : TT([this](void) { std::cout << this << std::endl; })...
{
}
};
int main(void)
{
T<A, B, C> t;
return 0;
}
Output:
0x7ffe84574e6f
0
0
My class template T inherits from its template parameter pack TT. Each type of TT expects a functor as constructor argument. When I try to pass a functor that captures this during the constructor calls, all but the first constructor call of the expansion actually receive a functor that captured nullptr as this. If I delegate the functor creation to a member function, it works as intended:
template<typename ... TT>
struct T : TT...
{
T( ) : TT(genF())...
{
}
f_t genF( ) { return [this](void) { std::cout << this << std::endl; }; }
};
Output:
0x7ffefca4e61f
0x7ffefca4e61f
0x7ffefca4e61f
(Compiler used is GCC 4.6.3)
What causes this behavior? Is it a compiler bug? Or am I missing something?

Related

Providing generic interface with TMP and SFINAE

At the moment, I have the below working code where using class X, I provide a generic interface for multiple classes - I only expect a static f function to be present, but neither do I fix the return type nor the parameters:
#include <iostream>
#include <type_traits>
class A {
public:
static void f()
{
std::cout << "A::f()" << std::endl;
}
};
class B {
public:
static size_t f(std::string const& s_)
{
std::cout << "B::f()" << std::endl;
return s_.size();
}
};
class C {
};
template <typename T>
class X {
public:
static
void
f(...)
{
std::cout << "Operation not supported!" << std::endl;
}
template <typename... Args>
static
std::result_of_t<decltype(&T::f)(Args...)>
f(Args&&... args_)
{
return T::f(std::forward<Args>(args_)...);
}
};
int main()
{
X<A>::f(); // Compiles, but unexpected overload!
auto const x = X<B>::f("Hello"); // Works just fine
std::cout << x << std::endl;
// X<C>::f(); // Does NOT compile!
return 0;
}
However, I've got multiple problems with it (as marked above in the comments):
If I allow the function to be not present and uncomment the line
using C as a template parameter, the code does not compile, it
still expects C to have a function f:
In instantiation of ‘class X<C>’:
required from here
error: ‘f’ is not a member of ‘C’
std::result_of_t<decltype(&T::f)(Args...)>
Based on this, I expected the ellipsis parameter do the trick.
On the other hand, even if this worked, I would have another problem: though A provides f, the overload with
the ellipsis parameter is picked during overload resolution - where, of course, f provided by A is preferred.
(Used compiler: g++ (Ubuntu 8.1.0-5ubuntu1~16.04) 8.1.0; used standard: C++14.)
Any help solving the above problems (preferably both, at the same time) is welcomed.
I propose the following X struct
template <typename T>
struct X
{
static void g (...)
{ std::cout << "Operation not supported!" << std::endl; }
template <typename ... As, typename U = T>
static auto g(int, As && ... as)
-> decltype( U::f(std::forward<As>(as)...) )
{ return T::f(std::forward<As>(as)...); }
template <typename ... As>
static auto f (As && ... as)
{ return g(0, std::forward<As>(as)...); }
};
The points are
(1) Passing through a g() function with an additional unused parameter (int in the variadic version, adsorbed by ... in the "not supported version"), permit to select the variadic version (called with 0 that is an int), when sizeof...(As) == 0 and both g() functions are available. This because int is a better match (in an exact match) for int as .... But when the variadic version isn't available (see point (2)), the "non supported" version is still available (the only one available) and selected
(2) You have to SFINAE enable/disable the variadic version according the fact that the f() static method is (or ins't) available in T. Unfortunately T is a template argument of the class, not of the g() static method, so you can use it for SFINAE. The trick is SFINAE operate over an additional template parameter, U, that is defaulted to T
// ------------------------VVVVVVVVVVVVVV additional U (defaulted to T) template type
template <typename ... As, typename U = T>
static auto g(int, As && ... as)
-> decltype( U::f(std::forward<As>(as)...) )
// -------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//
// SFINAE enable this g() if (and only if) the call
// U::f(std::forward<As>(as)...) is valid
The following is a simplified working example
#include <iostream>
#include <type_traits>
struct A
{ static void f() { std::cout << "A::f()" << std::endl; } };
struct B
{
static size_t f(std::string const& s_)
{ std::cout << "B::f()" << std::endl; return s_.size(); }
};
struct C
{ };
template <typename T>
struct X
{
static void g (...)
{ std::cout << "Operation not supported!" << std::endl; }
template <typename ... As, typename U = T>
static auto g(int, As && ... as)
-> decltype( U::f(std::forward<As>(as)...) )
{ return T::f(std::forward<As>(as)...); }
template <typename ... As>
static auto f (As && ... as)
{ return g(0, std::forward<As>(as)...); }
};
int main ()
{
X<A>::f(); // now call variadic version
auto const x = X<B>::f("Hello"); // Works just fine as before
std::cout << x << std::endl;
X<C>::f(); // now compile
}

Template specialization using another class that implicit-converts to it

I don't know if this is possible, but I would like to understand better how this works.
Can a class implict convertsion operation be used to match a template parameter?
This is what I want to do.
#include <iostream>
template<typename T>
struct Value {
};
template<>
struct Value<int> {
static void printValue(int v) {
std::cout << v << std::endl;
}
};
struct Class1 {
int value;
};
/*
template<>
struct Value<Class1*> {
static void printValue(Class1* v) {
std::cout << v->value << std::endl;
}
};
*/
template<typename X>
struct ClassContainer {
ClassContainer(X *c) : _c(c) {}
operator X*() { return _c; }
X *_c;
};
template<typename X>
struct Value<ClassContainer<X>> {
static void printValue(ClassContainer<X> v) {
std::cout << static_cast<X*>(v)->value << std::endl;
}
};
template<typename X>
void doPrintValue(X v)
{
Value<X>::printValue(v);
}
int main(int argc, char *argv[])
{
doPrintValue(10);
Class1 *c = new Class1{ 20 };
//doPrintValue(c); // error C2039: 'printValue': is not a member of 'Value<X>'
ClassContainer<Class1> cc(c);
doPrintValue(cc);
std::cout << "PRESS ANY KEY TO CONTINUE";
std::cin.ignore();
}
ClassContainer has an implict conversion to X*. Is it possible to match ClassContainer passing only X*?
If you want the template class for pointers to behave like the template class for something else, just inherit:
template<typename T>
struct Value<T*> : Value<ClassContainer<T>> {};
It will inherit the public printValue function, which accepts a parameter that can be constructed from T*, and everything will be implicitly converted as expected.
See it all live here.

Specialize member pointer template argument resolution

Having guard class on C++11 that is responsible to invoke some member function on scope exit:
template <class T, void (T::*op)()>
struct Guard
{
Guard(T*g):
_g(g){}
~Guard()
{
(_g->*op)();
}
T*_g;
};
Usage is very simple:
typedef Guard<Foo, &Foo::bar> FooGuard;
...
FooGuard g(&foo);
My question originated from existing shared_ptr<Foo>. How to create specialization that keeps shared_ptr<T> instead of T*
What I've already tried:
template <class T, void (T::*op)()>
struct Guard<std::shared_ptr<T>, op>
{
Guard(std::shared_ptr<T>& g):
_g(g){}
~Guard()
{
((*_g).*op)();
}
std::shared_ptr<T> _g;
};
But during compilation on G<std::shared_ptr<Foo>, &Foo::bar> g2(foo); have foreseeable got:
error C2440: 'specialization' : cannot convert from 'overloaded-function' to 'void (__thiscall std::shared_ptr::* )(void)'
as #PiotrSkotnicki already pointed out, your specialization is not valid.
You could use something like the following, however the interface does not look that nice:
template <class T, class U, void (U::*op)()>
struct Guard
{
Guard(T*g):
_g(g){}
~Guard()
{
std::cout << "normal guard" << std::endl;
(_g->*op)();
}
T*_g;
};
template <class T, class U, void (U::*op)()>
struct Guard<std::shared_ptr<T>, U, op>
{
Guard(std::shared_ptr<T>& g):
_g(g){}
~Guard()
{
std::cout << "shared_ptr guard" << std::endl;
((*_g).*op)();
}
std::shared_ptr<T> _g;
};
Demo:
struct Foo
{
void bar()
{
std::cout << "Foo::bar()" << std::endl;
}
};
int main()
{
Foo foo;
{
typedef Guard<Foo, Foo, &Foo::bar> FooGuard;
FooGuard g(&foo);
}
std::shared_ptr<Foo> foo_ptr = std::make_shared<Foo>();
{
typedef Guard<std::shared_ptr<Foo>, Foo, &Foo::bar> FooGuard;
FooGuard g(foo_ptr);
}
return 0;
}
Output:
normal guard
Foo::bar()
shared_ptr guard
Foo::bar()
live example
I would suggest using lambda functions instead and capture by value:
#include <functional>
#include <memory>
struct Guard
{
typedef std::function<void()> func_type;
Guard( const func_type& f ): func(f) {}
~Guard() { if (func) func(); }
func_type func;
};
struct Foo
{
void bar() {}
};
int main()
{
auto foo_ptr = std::make_shared<Foo>();
Guard g([foo_ptr](){ foo_ptr->bar(); }); // note the capture by value
}
Note that you are free to capture by reference too, if you want to guard an instance allocated on the stack for example.
If you really want to stick to the ugly way, I would suggest using deleters:
#include <string>
#include <memory>
#include <cstdio>
template < class T, void (T::*op)() >
struct Guard
{
Guard( T *p ): ptr( p, [](T*){} ) {}
Guard( const std::shared_ptr<T>& p ): ptr(p) {}
~Guard() { if (ptr) ((*ptr).*op)(); }
std::shared_ptr<T> ptr;
};
struct Foo
{
Foo( const char* n ): name(n) {}
void bar() { printf("Hello from %s\n",name.c_str()); }
std::string name;
};
int main()
{
auto foo1 = Foo("Bob");
auto foo2 = std::make_shared<Foo>("Alice");
Guard<Foo,&Foo::bar> g1(&foo1), g2(foo2);
}

'using' declaration as SFINAE

Could I use SFINAE (or another technique) for using declaration while private deriving from template class?
For better understanding see code below:
#include <iostream>
struct S1 {
void f() { std::cout << "S1::f\n"; }
};
struct S2 {
void f() { std::cout << "S2::f\n"; }
void g() { std::cout << "S2::g\n"; }
};
template <class T>
struct D : private T {
using T::f;
// using T::g; // need this only if T provides g() function
};
int main() {
D<S1>().f(); // ok. Prints 'S1::f'
D<S2>().f(); // ok. Prints 'S2::f'
D<S2>().g(); // fail. But wants to be ok and prints 'S2::g'
return 0;
}
How can I reach desired behaviour (if it possible)?
A variant of Bryan Chen's answer that looks uglier, but makes it easier to extend to multiple checks, and doesn't require duplicating the code that's shared between D<type-with-f> and D<type-without-f>, is to use an inheritance chain, where each step checks one additional member. The only duplication required is the inheritance of constructors, if appropriate.
struct A {
void f() { }
void g() { }
void i() { }
};
// The generic case. D<T, char[N]> simply provides what D<T, char[N+1]> provides.
template <typename T, typename U = char[1]>
struct D : D<T, char[sizeof(U) + 1]> {
using D<T, char[sizeof(U) + 1]>::D;
};
// The end of the chain. This is where T gets inherited. It declares all of its own
// specialisations as its friends, so that they can access other members of T.
template <typename T>
struct D<T, char[6]> : private T {
template <typename, typename>
friend struct D;
D(int) { }
void fun() { }
};
// Check for T::f.
template <typename T>
struct D<T, char[2 + !sizeof(&T::f)]> : D<T, char[3]> {
using D<T, char[3]>::D;
using T::f;
};
// Check for T::g.
template <typename T>
struct D<T, char[3 + !sizeof(&T::g)]> : D<T, char[4]> {
using D<T, char[4]>::D;
using T::g;
};
// Check for T::h.
template <typename T>
struct D<T, char[4 + !sizeof(&T::h)]> : D<T, char[5]> {
using D<T, char[5]>::D;
using T::h;
};
// Check for T::i.
template <typename T>
struct D<T, char[5 + !sizeof(&T::i)]> : D<T, char[6]> {
using D<T, char[6]>::D;
using T::i;
};
int main() {
D<A> d = 4; // ok: verify that constructors got inherited
// A &a = d; // error: verify that inheritance of A is private
d.f(); // ok: verify that f got inherited
d.g(); // ok: verify that g got inherited
// d.h(); // error: verify that h is not available
d.i(); // ok: verify that i got inherited
d.fun(); // ok: verify that the inheritance chain didn't get broken
}
Note: instead of checking &T::f, you may want to do something with std::declval<T>().f() instead. The former cannot handle overloaded functions.
C++ partial template specialization and use decltype(void(&T::g)) for SFINAE
#include <iostream>
#include <type_traits>
struct S1 {
void f() { std::cout << "S1::f\n"; }
};
struct S2 {
void f() { std::cout << "S2::f\n"; }
void g() { std::cout << "S2::g\n"; }
};
template <class T, class V = void>
struct D : private T {
using T::f;
};
template <class T>
struct D<T, decltype(void(&T::g))> : private T {
using T::f;
using T::g; // need this only if T provides g() function
};
int main() {
D<S1>().f(); // ok. Prints 'S1::f'
D<S2>().f(); // ok. Prints 'S2::f'
D<S2>().g(); // ok. Prints 'S2::g'
return 0;
}
Live Demo
Edit:
This is another approach that is more flexible, but I have no idea how does private virtual inheritance works with real use cases. Please let me know if it may cause any issue (e.g. UB).
#include <iostream>
#include <type_traits>
struct S1 {
void f() { std::cout << "S1::f\n"; }
};
struct S2 {
void f() { std::cout << "S2::f\n"; }
void g() { std::cout << "S2::g\n"; }
};
struct S3 {
void g() { std::cout << "S3::g\n"; }
};
template <class T, class = void>
struct D_f {};
template <class T>
struct D_f<T, decltype(void(&T::f))> : private virtual T {
using T::f;
};
template <class T, class = void>
struct D_g {};
template <class T>
struct D_g<T, decltype(void(&T::g))> : private virtual T {
using T::g;
};
template <class T>
struct D : D_f<T>, D_g<T> {
};
int main() {
D<S1>().f();
D<S2>().f();
D<S2>().g();
D<S3>().g();
return 0;
}
Live Demo

How to use functor as a member in class template?

I was trying to use a functor as a std::function object inside a class template. Below is what I have done so far.
//! the functor class template
template<typename T>
struct func
{
void operator ()(T t)
{
std::cout << t << "\n";
}
};
//! the class template that holds a std::function object as a member
template<typename T>
struct Foo
{
std::function<void(T)> bar = func<T>();
};
int main()
{
Foo<int> foo;
return 0;
}
It was complained that
error: conversion from 'func<int>' to non-scalar type 'std::function<void(int)>' requested
struct Foo
^
Is it possible to do so? How to fix it?
You can either make it static and initialize it outside class-scope, or initialize it in the constructor. Tested on GCC 4.7.2.
template<typename T>
struct Foo
{
static std::function<void(T)> bar;
};
template <typename T>
std::function<void(T)> Foo<T>::bar = func<T>();
EDIT
In C++11, you can also use brace-initialization:
std::function<void(T)> bar { func<T>() };
Different ways to use std::function in a non-static data member initializer
#include <functional>
#include <iostream>
#define ENABLE_CONVERSION 1
template<typename T>
struct func
{
void operator ()(T t)
{
std::cout << "Function: " << t << "\n";
}
#if ENABLE_CONVERSION
// FIX: error: conversion from ‘func<int>’ to non-scalar type
// ‘std::function<void(int)>’ requested
operator std::function<void(T)> () { return std::function<void(T)>(*this); }
#endif
};
template<typename T>
struct Foo
{
std::function<void(T)> bar0 = std::function<void(T)>(func<T>());
std::function<void(T)> bar1{func<T>()};
// Error without ENABLE_CONVERSION
std::function<void(T)> bar2 = func<T>();
static std::function<void(T)> bar3;
void operator() () {
bar0(0);
bar1(1);
bar2(2);
bar3(3);
}
};
template<typename T>
std::function<void(T)> Foo<T>::bar3 = func<T>();
template<typename T>
void goo() {
// This compiles without ENABLE_CONVERSION:
// What is the difference to non-static data member initializers ?
std::function<void(T)> g = func<T>();
g(4);
}
int main()
{
Foo<int> foo;
foo();
goo<int>();
return 0;
}
Additional question
I tried to find differences between variable brace-or-equal-initializer
and the non-static data member brace-or-equal-initializer. I found nothing.
What is the difference between
std::function<void(T)> bar2 = func<T>();
and
std::function<void(T)> g = func<T>();
when ENABLE_CONVERSION is zero?
In your case std::function is optional, use direct functor itself.
//! the functor class template
template<typename T>
struct func
{
void operator ()(T t)
{
std::cout << t << "\n";
}
};
//! the class template that holds a std::function object as a member
template<typename T>
struct Foo
{
//std::function<void(T)> bar = func<T>(); <-- **removed, because std::function isn't cheap as func<T>**.
func<T> bar;//default initialized itself.
};
int main()
{
Foo<int> foo;
foo.bar(24);//prints 24.
return 0;
}
EDIT:
In common case, move template from struct declration to the operator, i.e. as:
struct func
{
template< typename T >
void operator()(T t ) const { std::cout << t << '\n'; }
};
struct Foo
{
func m_func;
};
int main(){
Foo f;
f.m_func(24); // prints 24
f.m_func("hello world"); // prints "hello world"
f.m_func(3.143); // prints 3.143
// and etc.,
};
in c++14, std::less<>, std::greater<> and more other functors template keyword moved to the operator declaration, instead of struct declaration, it's help more generic comparation.
Edit2: You may use following technicus:
struct func{
template< typename T > void operator()(T t) const{ std::cout << t << '\n';}
};
template< typename T, typename Functor> // Functor as template
struct Foo
{
Functor m_Functor; //--> functor member
T m_Data; // or something else.
};
// create `makeFoo` for auto deduced functor type.
template< typename T, typename Functor>
Foo<T,Functor> makeFoo(Functor f, T t ) { return {f,t}; }
int print(int i, int j){ std::cout << i+j << '\n' ;}
int main()
{
auto foo = makeFoo(24, func{} );
// use foo
auto foo2 = makeFoo("hello", std::bind(print, 2, _1) );
// use foo2
}