specialization on const member function pointers - c++

I am trying to specialize some utility code on const member functions, but have problems to get a simple test-case to work.
To simplify the work i am utilizing Boost.FunctionTypes and its components<FunctionType> template - a MPL sequence which should contain the tag const_qualified for const member functions.
But using the test-code below, the specialization on const member functions fails. Does anybody know how to make it work?
The test-code prints out (using VC8 and boost 1.40):
non-const
non-const
Expected output is:
non-const
const
The test-code itself:
#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/mpl/contains.hpp>
namespace ft = boost::function_types;
namespace mpl = boost::mpl;
template<typename F>
struct select
{
template<bool IsConst /* =false */>
struct helper {
static void f() { std::cout << "non-const" << std::endl; }
};
template<>
struct helper</* IsConst= */ true> {
static void f() { std::cout << "const" << std::endl; }
};
typedef ft::components<F> components;
typedef typename mpl::contains<components, ft::const_qualified>::type const_qualified;
typedef helper<const_qualified::value> result;
};
typedef boost::function<void (void)> Functor;
template<typename MF>
Functor f(MF f)
{
return boost::bind(&select<MF>::result::f);
}
class C
{
public:
void f1() {}
void f2() const {}
};
int main()
{
f(&C::f1)(); // prints "non-const" as expected
f(&C::f2)(); // prints "non-const", expected "const"
}

While its still unclear to me why the approach via function_types::components<> doesn't work, i realized that there is a simpler approach with Boost.FunctionTypes to specialize on const member functions:
The classification meta functions like is_member_function_pointer<> optionally take a tag parameter ...
template<typename F>
struct select
{
/* ... helper-struct as before */
typedef ft::is_member_function_pointer<F, ft::const_qualified> const_qualified;
typedef helper<const_qualified::value> result;
};

I have not tested it, but shouldn't
typedef mpl::contains<components, ft::const_qualified> const_qualified;
be
typedef typename mpl::contains<components::type, ft::const_qualified>::type const_qualified;

Related

Template type erasure

I am wondering whether there is a practical way of writing something like the following code using the C++17 standard:
#include <string>
#include <functional>
#include <unordered_map>
template <class Arg>
struct Foo
{
using arg_type = Arg;
using fun_type = std::function< void(Arg&) >;
fun_type fun;
void call( Arg& arg ) { fun(arg); }
};
struct Bar
{
using map_type = std::unordered_map<std::string,Foo>; // that's incorrect
map_type map;
auto& operator[] ( std::string name ) { return map[name]; }
};
In the code above, the template argument of class Foo corresponds to the input type of some unary function which returns nothing. Different instances of Foo with different template types correspond to functions taking arguments of different types. The class Bar simply aims at assigning a name to these functions, but obviously the current declaration of the map is incorrect because it needs to know about the template type of Foo.
Or does it?
Doing this with a compile-time check is, unfortunately, not feasible. You can, however, provide that functionality with a runtime check.
A map's value type can only be one single type, and Foo<T> is a different type for each T. However, we can work around this by giving every Foo<T> a common base class, have a map of pointers to it, and use a virtual function to dispatch call() to the appropriate subclass.
For this though, the type of the argument must also always be the same. As mentioned by #MSalters, std::any can help with that.
Finally, we can wrap all that using the pimpl pattern so that it looks like there's just a single neat Foo type:
#include <cassert>
#include <string>
#include <functional>
#include <any>
#include <unordered_map>
#include <memory>
struct Foo {
public:
template<typename T, typename FunT>
void set(FunT fun) {
pimpl_ = std::make_unique<FooImpl<T, FunT>>(std::move(fun));
}
// Using operator()() instead of call() makes this a functor, which
// is a little more flexible.
void operator()(const std::any& arg) {
assert(pimpl_);
pimpl_->call(arg);
}
private:
struct IFooImpl {
virtual ~IFooImpl() = default;
virtual void call( const std::any& arg ) const = 0;
};
template <class Arg, typename FunT>
struct FooImpl : IFooImpl
{
FooImpl(FunT fun) : fun_(std::move(fun)) {}
void call( const std::any& arg ) const override {
fun_(std::any_cast<Arg>(arg));
}
private:
FunT fun_;
};
std::unique_ptr<IFooImpl> pimpl_;
};
// Usage sample
#include <iostream>
void bar(int v) {
std::cout << "bar called with: " << v << "\n";
}
int main() {
std::unordered_map<std::string, Foo> table;
table["aaa"].set<int>(bar);
// Even works with templates/generic lambdas!
table["bbb"].set<float>([](auto x) {
std::cout << "bbb called with " << x << "\n";
});
table["aaa"](14);
table["bbb"](12.0f);
}
see on godbolt

Invalid use of incomplete type with templates and decltype

I need to make the following work.
This is a reduced version of my actual code, but basically the difficulty is the same, i.e., to deduce the return type of a factory method.
Specifically, I need either the second or third variant of DeduceObjectT (both commented), instead of the first, which requires the FactoryT::ObjectT typedef.
#include <string>
#include <utility>
#include <memory>
template<class FactoryT>
using DeduceObjectT = typename FactoryT::ObjectT;
//template<class FactoryT>
//using DeduceObjectT = typename decltype(std::declval<FactoryT>().create())::element_type;
//template<class FactoryT>
//using DeduceObjectT = typename std::result_of<decltype(&FactoryT::create)(FactoryT)>::type::element_type;
template<class FactoryT>
struct FactoryUser
{
typedef DeduceObjectT<FactoryT> ObjectT;
};
template<class FactoryUserT>
struct Foo
{
typedef typename FactoryUserT::ObjectT ObjectT;
};
struct StringFactory
{
typedef std::string ObjectT; // want to omit this
std::unique_ptr<std::string> create()
{
return nullptr;
}
Foo<FactoryUser<StringFactory>> t;
};
int main()
{
StringFactory f;
return 0;
}
After numerous tries I still get 'error: invalid use of incomplete type ‘struct StringFactory’'.
I also tried deducing the type by means of a default template argument of FactoryUser.
I really don't understand, why am I getting the error considering that the point that triggers instantiation of all templates is at the end -- the line that declares the data member t.
Compiler is gcc 4.7.3. with -std=c++0x -O0
Try something like this instead:
template <typename Factory>
struct ProductTypedef
{
typedef typename decltype(std::declval<Factory>().create())::element_type ObjectT;
};
struct StringFactory : public ProductTypedef<StringFactory> // CRTP
{
std::unique_ptr<std::string> create()
{
return nullptr;
}
};
You can alter Foo a little bit for your code to work:
#include <string>
#include <utility>
#include <memory>
template<class FactoryT>
using DeduceObjectT = typename FactoryT::ObjectT;
template<class FactoryT>
struct FactoryUser
{
typedef DeduceObjectT<FactoryT> ObjectT;
};
// Provide a way for ObjectType to be specified at the time
// the template is instantiated.
template<class FactoryUserT, typename ObjectType = typename FactoryUserT::ObjectT>
struct Foo
{
typedef ObjectType ObjectT;
};
struct StringFactory
{
std::unique_ptr<std::string> create()
{
return nullptr;
}
Foo<FactoryUser<StringFactory>, std::string> t;
};
int main()
{
StringFactory f;
return 0;
}

C++: Non generic method in generic class?

I am interested in defining a custom method for a generic class for only a particular data type. I am not sure whats a good way to implement it. I won't be able to access class variables if I place it outside the class so I think i can never get it to work that way. If i place it inside the class, its meant to work for any type T and not just the particular type. I have been able to get my code to work the latter way by just defining a generic version of it and sending only that type as input which i m interested in but is there a neater way to accomplish this?
Below is some code to make it clear
#include<iostream>
#include<string>
using namespace std;
template<typename T>
class abc
{
public:
void myvoid();
};
template<typename string>
void abc<string>::myvoid()
{
cout<<"This portion should execute only if an instance of class is called with a string parameter" ;
}
int main()
{
abc<int> int1;
abc<string> string1;
string1.myvoid(); //should work good
int1.myvoid(); //shouldnt execute myvoid
}
You can use static_assert to prevent compilation if the method in question is used with the wrong type:
#include <type_traits> // for std::is_same
template <typename T>
struct Foo
{
void foo() const {}
void bar() const
{
static_assert(std::is_same<T, int>::value, "T is not int");
}
};
int main()
{
Foo<double> fd;
fd.foo(); // OK
//fd.bar(); // ERROR: bar() only works with Foo<int>
Foo<int> fi;
fi.foo(); // OK
fi.bar(); // OK
}
Alternatively, you can use SFINAE to control the types for which the method in question exists.
template <typename T>
class Foo
{
public:
void foo() const {}
template<typename T2 = T,
typename = typename std::enable_if<std::is_same<T, int>::value>::type>
void bar() {}
};
See this related question.
This will give a linker error if you try to call bar() on a non-specialized type. This works on gcc 4.8 (see: http://ideone.com/KbwToR)
#include <iostream>
using namespace std;
struct Foo
{
template <class T>
void bar(T);
};
template<>
void Foo::bar<int>(int i)
{
cout << i << '\n';
}
int main()
{
Foo f;
f.bar(1);
f.bar("Fail!");
return 0;
}

Define multiple methods with parameters from variadic templates

I want to define a base template class in a way so that it takes variadic template arguments and defines a virtual method for each argument, where the parameter is the argument type.
E.g. Base<int, bool, string> should give me 3 virtual methods: Foo(int), Foo(bool), and Foo(string).
I tried the following:
template <typename Param>
struct BaseSingle
{
virtual void Foo(Param) {};
};
template <typename... Params>
struct Base : public BaseSingle<Params>...
{
};
Unfortunately, Foo becomes ambiguous. I can't get the using BaseSingle<Params>::Foo... syntax to work. Is there a way?
I know that, alternatively, I can recursively inherit from BaseSingle and pass in the remaining params. Are there perf implications of that?
Here is a suggestion that requires exact type matching:
#include <utility>
#include <typeinfo>
#include <string>
#include <iostream>
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
using namespace std;
// GCC demangling -- not required for functionality
string demangle(const char* mangled) {
int status;
unique_ptr<char[], void (*)(void*)> result(
abi::__cxa_demangle(mangled, 0, 0, &status), free);
return result.get() ? string(result.get()) : "ERROR";
}
template<typename Param>
struct BaseSingle {
virtual void BaseFoo(Param) {
cout << "Hello from BaseSingle<"
<< demangle(typeid(Param).name())
<< ">::BaseFoo" << endl;
};
};
template<typename... Params>
struct Base : public BaseSingle<Params>... {
template<typename T> void Foo(T&& x) {
this->BaseSingle<T>::BaseFoo(forward<T>(x));
}
};
int main() {
Base<string, int, bool> b;
b.Foo(1);
b.Foo(true);
b.Foo(string("ab"));
}
But IMO your own suggestion using recursive inheritance sounds more elegant.

iterating getters of a vector of pointers

I am trying to write an iterator class which returns a getter function return value when it is dereferenced. The code works fine, my only problem is that I would like to write the member_ptr_functor using only one template parameter and not 3, since I am supposed to be able to deduce the types of the argument and return value from the member function type. I think the problematic one is the argument type, I tried using boost::remove_ptr&, but I couldn't compile it.
#include <iostream>
#include <vector>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp>
using namespace boost;
using namespace std;
class CTest
{
private:
int m_x;
public:
CTest(int x) : m_x(x)
{
}
const int& GetX() const
{
return m_x;
}
};
template<typename MemFunType, typename ArgumentType, typename ResultType>
class member_ptr_functor : public unary_function<ArgumentType, ResultType>
{
private:
MemFunType m_MemFun;
public:
typedef ArgumentType argument_type;
typedef ResultType result_type;
member_ptr_functor(MemFunType MemFun) : m_MemFun(MemFun)
{
}
result_type operator() (argument_type arg) const
{
return m_MemFun(&arg);
}
};
template<typename MemFunType, typename ArgumentType, typename ResultType>
member_ptr_functor<MemFunType, ArgumentType, ResultType> make_member_ptr_functor(MemFunType MemFun)
{
return member_ptr_functor<MemFunType, ArgumentType, ResultType>(MemFun);
}
class CPrintFunctor : public unary_function<int, void>
{
public:
void operator() (const int n) const
{
cout << n << endl;
}
};
int main()
{
typedef vector<CTest> Container_t;
Container_t v;
v.push_back(CTest(1));
CPrintFunctor PF;
Container_t::const_iterator itStart = v.begin();
Container_t::const_iterator itEnd = v.end();
typedef member_ptr_functor<const_mem_fun_t<const int&, CTest> , CTest, const int&> member_ptr_functor_t;
member_ptr_functor_t MemberPtrFunctor = member_ptr_functor_t(mem_fun(&CTest::GetX));
typedef transform_iterator<member_ptr_functor_t, Container_t::const_iterator, const int&, const int> transform_iterator_t;
transform_iterator_t itTransformStart = make_transform_iterator(itStart, MemberPtrFunctor);
transform_iterator_t itTransformEnd = make_transform_iterator(itEnd, MemberPtrFunctor);
for_each(itTransformStart, itTransformEnd, PF);
return 0;
}
Hagai.
This does not answer your question directly but rather suggests alternative approach.
You are already using Boost, so why do you not take it one step further, use Boost.Range:
#include <boost/functional.hpp>
#include <boost/range.hpp>
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/transformed.hpp>
// ...
int main ()
{
// ...
boost::range::for_each (
boost::adaptors::transform (v, boost::mem_fun_ref (&CTest::GetX)),
PF);
}
This lets you write the functionality that you want without having to define own functors and without using too many typedefs.