Specializing templates based on methods - c++

Recently I've been programming a lot in Java, now I'm coming back to my C++ roots (I really started missing the pointers and segmentation faults). Knowing that C++ has a broad support for templates I was wondering whether it has some capabilities of Java which could be useful for writing generalized code. Lets say I'have two groups of classes. One of them has the first() method, the other one has the second() method. Is there a way of specializing the templates to be picked by the compiler depending on the methods one class possesses? I'm aiming at behavior which is similar to the one of Java:
public class Main {
public static void main(String[] args) {
First first = () -> System.out.println("first");
Second second = () -> System.out.println("second");
method(first);
method(second);
}
static <T extends First> void method(T argument) {
argument.first();
}
static <T extends Second> void method(T argument) {
argument.second();
}
}
Where First and Second are interfaces. I know I could group both of these groups by deriving each of them from an upper class, but it's not always possible (no autoboxing in C++ and some classes don't inherit from a common ancestor).
A good example of my needs is the STL library, where some classes have methods like push() and some others have insert() or push_back(). Lets say I want to create an function which has to insert multiple values into an container using an variadic function. In Java it's easy to perform because collections have a common ancestor. In C++ on the other hand it's not always the case. I tried it by duck-typing, but the compiler yields an error message:
template <typename T>
void generic_fcn(T argument) {
argument.first();
}
template <typename T>
void generic_fcn(T argument) {
argument.second();
}
So my question is: Is implementing such behavior possible without creating unnecessary boileplate code by specializing every single case?

Instead of <T extends First>, you will use something we call sfinae. This is a technique about adding constaints on a function based on parameter types.
Here's how you'd do it in c++:
template <typename T>
auto generic_fcn(T argument) -> void_t<decltype(argument.first())> {
argument.first();
}
template <typename T>
auto generic_fcn(T argument) -> void_t<decltype(argument.second())> {
argument.second();
}
For the function to exist, the compiler will need the type of argument.second() or the type of argument.first(). If the expression does not yield a type (ie. T has not a first() function), the compiler will try another overload.
void_t is implemented as follow:
template<typename...>
using void_t = void;
Another great thing is that if you have such class:
struct Bummer {
void first() {}
void second() {}
};
Then the compiler will effectively tell you that the call is ambiguous because the type match both constraints.
If you really want to test if a type extends another (or implement, in c++ it's the same thing) you can use the type trait std::is_base_of
template <typename T>
auto generic_fcn(T argument) -> std::enable_if_t<std::is_base_of<First, T>::value> {
argument.first();
}
template <typename T>
auto generic_fcn(T argument) -> std::enable_if_t<std::is_base_of<Second, T>::value> {
argument.second();
}
To read more about this topic, check sfinae on cpprefence, and you can check available traits provided by the standard library.

so many options available in c++.
My preference is to favour free functions and return any result type correctly.
#include <utility>
#include <type_traits>
#include <iostream>
struct X
{
int first() { return 1; }
};
struct Y
{
double second() { return 2.2; }
};
//
// option 1 - specific overloads
//
decltype(auto) generic_function(X& x) { return x.first(); }
decltype(auto) generic_function(Y& y) { return y.second(); }
//
// option 2 - enable_if
//
namespace detail {
template<class T> struct has_member_first
{
template<class U> static auto test(U*p) -> decltype(p->first(), void(), std::true_type());
static auto test(...) -> decltype(std::false_type());
using type = decltype(test(static_cast<T*>(nullptr)));
};
}
template<class T> using has_member_first = typename detail::has_member_first<T>::type;
namespace detail {
template<class T> struct has_member_second
{
template<class U> static auto test(U*p) -> decltype(p->second(), void(), std::true_type());
static auto test(...) -> decltype(std::false_type());
using type = decltype(test(static_cast<T*>(nullptr)));
};
}
template<class T> using has_member_second = typename detail::has_member_second<T>::type;
template<class T, std::enable_if_t<has_member_first<T>::value>* =nullptr>
decltype(auto) generic_func2(T& t)
{
return t.first();
}
template<class T, std::enable_if_t<has_member_second<T>::value>* =nullptr>
decltype(auto) generic_func2(T& t)
{
return t.second();
}
//
// option 3 - SFNAE with simple decltype
//
template<class T>
auto generic_func3(T&t) -> decltype(t.first())
{
return t.first();
}
template<class T>
auto generic_func3(T&t) -> decltype(t.second())
{
return t.second();
}
int main()
{
X x;
Y y;
std::cout << generic_function(x) << std::endl;
std::cout << generic_function(y) << std::endl;
std::cout << generic_func2(x) << std::endl;
std::cout << generic_func2(y) << std::endl;
std::cout << generic_func3(x) << std::endl;
std::cout << generic_func3(y) << std::endl;
}

You can dispatch the call as it follows:
#include<utility>
#include<iostream>
struct S {
template<typename T>
auto func(int) -> decltype(std::declval<T>().first(), void())
{ std::cout << "first" << std::endl; }
template<typename T>
auto func(char) -> decltype(std::declval<T>().second(), void())
{ std::cout << "second" << std::endl; }
template<typename T>
auto func() { return func<T>(0); }
};
struct First {
void first() {}
};
struct Second {
void second() {}
};
int main() {
S s;
s.func<First>();
s.func<Second>();
}
Method first is preferred over second if a class has both of them.
Otherwise, func uses function overloading to test the two methods and choose the right one.
This technique is called sfinae, use this name to search on the web for further details.

Here is a little library that helps you determine if a member exists.
namespace details {
template<template<class...>class Z, class always_void, class...>
struct can_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, std::void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply=details::can_apply<Z, void, Ts...>;
Now we can write has first and has second easily:
template<class T>
using first_result = decltype(std::declval<T>().first());
template<class T>
using has_first = can_apply<first_result, T>;
and similarly for second.
Now we have our method. We want to call either first or second.
template<class T>
void method_second( T& t, std::true_type has_second ) {
t.second();
}
template<class T>
void method_first( T& t, std::false_type has_first ) = delete; // error message
template<class T>
void method_first( T& t, std::true_type has_first ) {
t.first();
}
template<class T>
void method_first( T& t, std::false_type has_first ) {
method_second( t, has_second<T&>{} );
}
template<class T>
void method( T& t ) {
method_first( t, has_first<T&>{} );
}
this is known as tag dispatching.
method calls the method_first which is determined if T& can be invoked with .first(). If it can be, it calls the one that calls .first().
If it cannot, it calls the one that forwards to method_second and tests if it has .second().
If it has neither, it calls an =delete function, which generates an error message at compile time.
There are many, many, many ways to do this. I personally like tag dispatching because you can get better error messages out of failure to match than SFIANE generates.
In C++17 you can be more direct:
template<class T>
void method(T & t) {
if constexpr (has_first<T&>{}) {
t.first();
}
if constexpr (has_second<T&>{}) {
t.second();
}
}

Related

How to identify if a method of underlying type held by a shared_ptr can be invoked with one or no parameters at compile time

Using C++ 17. I have the following:
template <typename T>
using ptr_t = std::shared_ptr<const T>;
class some_type;
class A { some_type foo() const; }
class B { some_type foo() const; }
class C { some_type foo(int) const; }
std::variant<ptr_t<A>, ptr_t<B>, ptr_t<C>>;
A variant holds shared_ptr(s) to different types. All expected to have function foo() that may be void or take a parameter. I will then have a visitor that would correctly dispatch foo, something like this (conceptually):
struct visitor
{
template <typename T>
ptr_t<some_type> operator()(const T& config) const
{
if constexpr (// determine if foo() of the underlying type of a shared_ptr can be called with int param)
return config->foo(15);
else
return config->foo();
}
is there a way to say this? I tried various ways but can't come with something that compiles. Template parameter, T, is ptr_t<A|B|C>.
std::is_invocable_v<Callable, Args...> is the way to go. Unfortunatelly, it will not compile just like that with if constexpr. It will either fail because "there is no operator()() overload", or there is no overload for operator taking Args....
I suggest you add a wrapper class for a callable and use it with a specialized alias template of std::variant instead of writing your own visitor. It will allow you to use std::visit seamlessly.
#include <type_traits>
#include <variant>
template <typename Callable>
class wrapped_callable
{
Callable c;
public:
wrapped_callable(Callable c)
: c(c)
{}
template <typename ... Args>
constexpr decltype(auto) operator()(Args &&... args) const
{
return _invoke(std::is_invocable<Callable, Args...>{}, c, std::forward<Args>(args)...);
}
private:
using _invocable = std::true_type;
using _non_invocable = std::false_type;
template <typename T, typename ... Args>
constexpr static decltype(auto) _invoke(_invocable, const T& t, Args &&... args)
{
return t(std::forward<Args>(args)...);
}
template <typename T, typename ... Args>
constexpr static decltype(auto) _invoke(_non_invocable, const T& t, Args ... args)
{
return t();
}
};
template <typename ... T>
using variant_callable = std::variant<wrapped_callable<T>...>;
struct int_callable
{
int operator()(int i) const
{
return i;
}
};
struct non_callable
{
int operator()() const
{
return 42;
}
};
#include <iostream>
int main()
{
using variant_t = variant_callable<int_callable, non_callable>;
// 23 is ignored, 42 is printed
std::visit([](const auto &callable){
std::cout << callable(23) << '\n';
}, variant_t{non_callable()});
// 23 is passed along and printed
std::visit([](const auto &callable){
std::cout << callable(23) << '\n';
}, variant_t{int_callable()});
}
Program returned: 0
42
23
https://godbolt.org/z/e6GzvW6n6
But The idea is not to have any specialization for all types in a variant as it will then require changing the visitor code every time a new type is added.
That is what template alias of std::variant<wrapped_callable<T>...> for. You just add append a new type to the list, that's it.
Take notice, that it does not depend on if constexpr. So if you manage to provide your own variant and is_invocable_v, it will work for C++14. For C++11 possibly, but some modifications regarding constexpr functions might be needed.
Of course you can implement your visitor in the same manner if you want to use std::shared_ptr istead of a callable.
But I don't see any reason to use:
visitor + smart pointer. Just use a smart pointer - it will give you runtime polymorphism in a "classic" way (via virtual inheritence)
why std::shared_ptr? Do you really need to share the ownership? Just stick with std::unique_ptr

Template specialisation on substitution failure

Consider this function:
template<typename T>
void f(T c) {
std::cout<<c<<std::endl;
}
You see that it will not compile for types which does not have an operator<< overload.
Now I want to write a function that acts like a fallback for this case.
/*Fallback*/
template<>
void f(T c) {
std::cout<<"Not Printing"<<std::endl;
}
How must this function be defined to do the job?
Pre-C++20
To have these overloads work in a fallback way, we can start by defining a trait that detects the validity of the expression involving operator <<
namespace detail {
template<typename T, typename = void>
struct streamable : std::false_type{};
template<typename T>
struct streamable<T, decltype(std::declval<std::ostream&>() << std::declval<T&>(), void())> : std::true_type {};
}
It's just your typical use of the detection idiom with as little extra library support as possible. Depending on the standard you are building against, this may be written in other ways (for instance std::void_t can be used, if available).
Now, the two overloads can be specified rather simply:
template<typename T>
auto f(T c) -> std::enable_if_t<detail::streamable<T>::value, void> {
std::cout<<c<<std::endl;
}
template<typename T>
auto f(T c) -> std::enable_if_t<!detail::streamable<T>::value, void> {
/// other code
}
Post C++20, concepts and constraints make it a whole lot easier. It can even be written ad-hoc:
template<typename T>
requires requires(std::ostream& os, T& c) { os << c; }
void f(T c) {
std::cout<<c<<std::endl;
}
template<typename T> // No extra step, subsumed by the above when possible
void f(T c) {
// other code
}
With concepts (C++20), we can achieve this like so:
template<typename T>
concept Streamable = requires(T t){std::declval<std::ostream&>() << t; };
template<Streamable T>
void f(T c) { std::cout << c << std::endl; }
/*Fallback*/
template<typename T>
void f(T c) { std::cout << "fallback" < <std::endl; }
Demo
Test:
struct Foo{};
int main()
{
Foo foo;
f(foo); // prints "fallback"
int a = 42;
f(a); // prints "42"
}
If you want to make doubly sure that your fallback will only happen if your type is not Streamable, you can constrain it, too:
template<typename T> requires (!Streamable<T>)
void f(T c) { /*...*/ }
You have several options of doing this. Arguably the most elegant way is to define your own type trait (similar to the ones in type_traits).
Let's define a is_streamable type trait. It takes two template arguments: S is the data type of the file stream (e.g. std::ostream or std::fstream or any other type that defines a custom streaming operator that is compatible with T) and secondly the data type of the object to be streamed into this file stream T:
template<typename S, typename T, typename = void>
struct is_streamable : std::false_type {
};
template<typename S, typename T>
struct is_streamable<S, T, decltype(std::declval<S&>() << std::declval<T&>(), void())> : std::true_type {
};
So far this type trait compiles with C++11 and onwards. For C++14 and later we can create a convenient alias for it similar to other type traits in C++17:
template <typename S, typename T>
static constexpr is_streamable_v = is_streamable<S,T>::value;
This type trait will now be the basis for the next step which will make use of SFINAE (C++11 onwards), constexpr if (C++17 onwards) or concepts (C++20).
In C++11 you could achieve this with either by putting the different implementations into partial specialisations of the same struct and call it with a helper function:
class f_imp {
};
template <typename T>
class f_imp<T,true> {
public:
static constexpr void imp(T c) {
std::cout << "streamable: " << c << std::endl;
}
};
template <typename T>
class f_imp<T,false> {
public:
static constexpr void imp(T c) {
std::cout << "not streamable" << std::endl;
}
};
template <typename T>
void f(T c) {
return f_imp<T,is_streamable<std::ostream,T>::value>::imp(c);
}
Try it here!
Alternatively you could apply SFINAE either by adding a second input parameter or applying it to the return type:
template<typename T, typename std::enable_if<is_streamable<std::ostream,T>::value>::type* = nullptr>
void f(T t) {
std::cout << "streamable" << std::endl;
}
template<typename T, typename std::enable_if<!is_streamable<std::ostream,T>::value>::type* = nullptr>
void f(T t) {
std::cout << "not streamable" << std::endl;
}
Try it here!
In C++17 you can actually use a constexpr if to avoid adding a second template argument and overloading of the function altogether. You can insert all the code inside the function and use if constexpr in combination with std::is_same_v and our is_streamable_v to decide at compile time which branch of our code each template type should take. This is in particular convenient if adding two specialisations would result in duplicate code but it might be harder to read.
template<typename T>
void f(T c) {
if constexpr (is_streamable_v<std::ostream,T>) {
std::cout << "streamable:" << c << std::endl;
} else {
// Fallback
std::cerr << "not streamable" << std::endl;
}
return;
}
Try it here!
Finally in C++20 you could use this type trait to define a concepts such as streamable and not_streamable:
template <typename T>
concept streamable = is_streamable_v<std::ostream,T>;
template <typename T>
concept not_streamable = !streamable<T>;
Then you can go on to apply them to your two overloads of the functions
template <streamable T>
void f(T c) {
std::cout << "streamable: " << c << std::endl;
}
template <not_streamable T>
void f(T c) {
std::cout << "not streamable" << std::endl;
}
Try it here!
Be aware that you will have to also apply the same logic to any custom streaming operator of a templated class, e.g. of a templated vector. Instead of declaring the operator for any template parameter typename T you would have to only declare it for streamable element types only. In C++20 for example with said streamable concept:
template <streamable T>
std::ostream& operator << (std::ostream& os, std::vector<T> const& vec) {
for (auto const& v: vec) {
os << v << " ";
}
return os;
}
Otherwise - as the template argument to the is_streamable operator is std::vector<T> as a whole - the compiler sees the operator << for std::vector<T> without checking if it would result in a compilation error for an unstreamable type T which does not define the operator << itself.
Try it here!

how to forward the types of tuple to specialize other template?

currently I'm working on a dynamic container structure, which represents one pod value or has vector of pointers with same container type. The container has an interface optional<T> expect_value<T>() 。 For pod types the implemention is simple. For the non pod value, I would call expect_value<tuple<args...>>(), the args would be tuple as well. But when implement this function, I come across a trouble: how to redirect a.expect_value<tuple<args...>>() to a.expect_value_tuple<args...>>(). For example, the call to a.expect_value<tuple<int,int>() would return the result of a.expect_value_tuple<int, int>(). Because the argument is empty, I cant use the type deduce of unpacked arguments. Then the whole project just cant progress any more. Any ideas? Below is the minimal example for my intention.
#include <tuple>
#include <vector>
#include <optional>
#include <functional>
using namespace std;
template<typename T>
struct is_tuple_impl : std::false_type {};
template<typename... Ts>
struct is_tuple_impl<std::tuple<Ts...>> : std::true_type {};
template<typename T>
struct is_tuple : is_tuple_impl<std::decay_t<T>> {};
class my_container;
template<typename... args, size_t... arg_idx>
optional<tuple<args>...> get_tuple_value_from_vector(const vector<my_container*>& v_list, std::index_sequence<arg_idx...>)
{
auto temp_result = make_tuple((*v_list[arg_idx]).expect_value<arg>()...);
if(!(get<arg_idx>(temp_result) &&...))
{
return nullopt;
}
return make_tuple(get<arg_idx>(temp_result).value()...);
}
class my_container
{
public:
int value_type; // 1 for v_int 2 for v_list 0 empty
union
{
int v_int;
};
vector<my_container*> v_list;
template<typename T>
optional<T> expect_simple_value();
template<typename... args>
optional<tuple<args...>> expect_tuple_value();
template<typename T>
optional<T> expect_value();
};
template <typename T>
optional<T> my_container::expect_simple_value()
{
return nullopt;
}
template <>
optional<int> my_container::expect_simple_value()
{
if(value_type == 1)
{
return v_int;
}
return nullopt;
}
template<typename... args>
optional<tuple<args...>> my_container::expect_tuple_value()
{
if(v_list.size() == 0)
{
return nullopt;
}
for(const auto i: v_list)
{
if(!i)
{
return nullopt;
}
}
auto the_tuple_size = sizeof...(args);
if(v_list.size() != the_tuple_size)
{
return nullopt;
}
return get_tuple_value_from_vector<args...>(v_list, index_sequence_for<args...>{});
}
template <typename T>
optional<T> my_container::expect_value()
{
if(is_tuple<T>::value)
{
return expect_tuple_value<T>();
}
else
{
return expect_simple_value<T>();
}
}
int main()
{
my_container test_value;
test_value.value_type = 1;
test_value.v_int = 1;
auto result = test_value.expect_value<tuple<int, int>>();
if(result)
{
return 0;
}
else
{
return 1;
}
}
the heart of the problem is the line return expect_tuple_value<T>(); When logic goes there, the T should be tuple<args...>, but what I want is return return expect_tuple_value<args...>().
What about using template argument deduction and overload resolution through partial ordering of function template:
class my_container
{
public:
template<class T> optional<T> expect_value_simple();
template<class...Args> optional<tuple<Args...>> expect_value_tuple();
private:
template<class T> struct deduce_type{};
template<typename T>
auto expect_value_dispatching(deduce_type<T>){
return expect_value_simple<T>();
}
template<typename...Args>
auto expect_value_dispatching(deduce_type<tuple<Args...>>){
return expect_value_tuple<Args...>();
}
public:
template<typename T>
auto expect_value(){
return expect_value_dispatching(deduce_type<T>{});
}
};
(Demo)
The if before the line in question should be a constexpr if.
Unpacking of types is annoying to do without using a class helper. I can do it with some fancy c++14 lambda action tho.
template<class T>
struct tag_t{using type=T;};
template<class Tag>
using type=typename Tag::type;
template<class Tuple>
struct unpack_tuple;
template<class...Ts>
struct unpack_tuple<std::tuple<Ts...>> {
template<class F>
decltype(auto) operator()(F&& f)const {
return std::forward<F>(f)( tag_t<Ts>{}... );
}
};
#define TYPE_FROM(...) \
type< std::decay_t<decltype(__VA_ARGS__)> >
then we get
if constexpr(is_tuple<T>::value)
{
return unpack_tuple<T>{}([&](auto...tags){
return expect_tuple_value<TYPE_FROM(tags)...>();
});
}
else
{
return expect_simple_value<T>();
}
and done.
The core issue here is that you need to do argument deduction at least once to go back from a type to its variadic parameters. To do that, you must pass some instance of such a variadically-templated type to a function - but it does not have to be the original one.
Yakk's solution does this via a variadic lambda that is passed instances of tag-types (one per tuple type). The advantage here is that you can use a lambda instead of an explicit intermediary function every time.
Oliv's solution uses a monostate type which we can instantiate and pass to a function for type deduction. It's much cleaner but requires such an intermediary function for every use case.
Here is a (more or less theoretical) version combining both, using templated variadic lambdas (C++20, and they apparently don't even have clang support as of now):
template<class... Args>
struct MonostateTuple
{};
template<class... Args>
auto tupleToMonostate(std::tuple<Args...>)
{
return MonostateTuple<Args...>{};
}
template<class T, class F>
auto unpack_tuple(F&& f)
{
using MT = decltype(tupleToMonostate(std::declval<T>()));
return std::forward<F>(f)(MT{});
}
/// User code
template<class Tuple>
auto foo()
{
return unpack_tuple<Tuple>([&] <typename... Args> (MonostateTuple<Args...>) {
return expect_tuple_value<Args...>();
});
}
It's a bit more ugly in the lambda signature (not to mention the lack of compiler support again) but theoretically combines both advantages.

Detecting a function in C++ at compile time

Is there a way, presumably using templates, macros or a combination of the two, that I can generically apply a function to different classes of objects but have them respond in different ways if they do not have a specific function?
I specifically want to apply a function which will output the size of the object (i.e. the number of objects in a collection) if the object has that function but will output a simple replacement (such as "N/A") if the object doesn't. I.e.
NO_OF_ELEMENTS( mySTLMap ) -----> [ calls mySTLMap.size() to give ] ------> 10
NO_OF_ELEMENTS( myNoSizeObj ) --> [ applies compile time logic to give ] -> "N/A"
I expect that this might be something similar to a static assertion although I'd clearly want to compile a different code path rather than fail at build stage.
From what I understand, you want to have a generic test to see if a class has a certain member function. This can be accomplished in C++ using SFINAE. In C++11 it's pretty simple, since you can use decltype:
template <typename T>
struct has_size {
private:
template <typename U>
static decltype(std::declval<U>().size(), void(), std::true_type()) test(int);
template <typename>
static std::false_type test(...);
public:
typedef decltype(test<T>(0)) type;
enum { value = type::value };
};
If you use C++03 it is a bit harder due to the lack of decltype, so you have to abuse sizeof instead:
template <typename T>
struct has_size {
private:
struct yes { int x; };
struct no {yes x[4]; };
template <typename U>
static typename boost::enable_if_c<sizeof(static_cast<U*>(0)->size(), void(), int()) == sizeof(int), yes>::type test(int);
template <typename>
static no test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(yes) };
};
Of course this uses Boost.Enable_If, which might be an unwanted (and unnecessary) dependency. However writing enable_if yourself is dead simple:
template<bool Cond, typename T> enable_if;
template<typename T> enable_if<true, T> { typedef T type; };
In both cases the method signature test<U>(int) is only visible, if U has a size method, since otherwise evaluating either the decltype or the sizeof (depending on which version you use) will fail, which will then remove the method from consideration (due to SFINAE. The lengthy expressions std::declval<U>().size(), void(), std::true_type() is an abuse of C++ comma operator, which will return the last expression from the comma-separated list, so this makes sure the type is known as std::true_type for the C++11 variant (and the sizeof evaluates int for the C++03 variant). The void() in the middle is only there to make sure there are no strange overloads of the comma operator interfering with the evaluation.
Of course this will return true if T has a size method which is callable without arguments, but gives no guarantees about the return value. I assume wou probably want to detect only those methods which don't return void. This can be easily accomplished with a slight modification of the test(int) method:
// C++11
template <typename U>
static typename std::enable_if<!is_void<decltype(std::declval<U>().size())>::value, std::true_type>::type test(int);
//C++03
template <typename U>
static typename std::enable_if<boost::enable_if_c<sizeof(static_cast<U*>(0)->size()) != sizeof(void()), yes>::type test(int);
There was a discussion about the abilities of constexpr some times ago. It's time to use it I think :)
It is easy to design a trait with constexpr and decltype:
template <typename T>
constexpr decltype(std::declval<T>().size(), true) has_size(int) { return true; }
template <typename T>
constexpr bool has_size(...) { return false; }
So easy in fact that the trait loses most of its value:
#include <iostream>
#include <vector>
template <typename T>
auto print_size(T const& t) -> decltype(t.size(), void()) {
std::cout << t.size() << "\n";
}
void print_size(...) { std::cout << "N/A\n"; }
int main() {
print_size(std::vector<int>{1, 2, 3});
print_size(1);
}
In action:
3
N/A
This can be done using a technique called SFINAE. In your specific case you could implement that using Boost.Concept Check. You'd have to write your own concept for checking for a size-method. Alternatively you could use an existing concept such as Container, which, among others, requires a size-method.
You can do something like
template< typename T>
int getSize(const T& t)
{
return -1;
}
template< typename T>
int getSize( const std::vector<T>& t)
{
return t.size();
}
template< typename T , typename U>
int getSize( const std::map<T,U>& t)
{
return t.size();
}
//Implement this interface for
//other objects
class ISupportsGetSize
{
public:
virtual int size() const= 0;
};
int getSize( const ISupportsGetSize & t )
{
return t.size();
}
int main()
{
int s = getSize( 4 );
std::vector<int> v;
s = getSize( v );
return 0;
}
basically the most generic implementation is always return -1 or "NA" but for vector and maps it will return the size. As the most general one always matches there is never a build time failure
Here you go. Replace std::cout with the output of your liking.
template <typename T>
class has_size
{
template <typename C> static char test( typeof(&C::size) ) ;
template <typename C> static long test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
template<bool T>
struct outputter
{
template< typename C >
static void output( const C& object )
{
std::cout << object.size();
}
};
template<>
struct outputter<false>
{
template< typename C >
static void output( const C& )
{
std::cout << "N/A";
}
};
template<typename T>
void NO_OF_ELEMENTS( const T &object )
{
outputter< has_size<T>::value >::output( object );
}
You could try something like:
#include <iostream>
#include <vector>
template<typename T>
struct has_size
{
typedef char one;
typedef struct { char a[2]; } two;
template<typename Sig>
struct select
{
};
template<typename U>
static one check (U*, select<char (&)[((&U::size)!=0)]>* const = 0);
static two check (...);
static bool const value = sizeof (one) == sizeof (check (static_cast<T*> (0)));
};
struct A{ };
int main ( )
{
std::cout << has_size<int>::value << "\n";
std::cout << has_size<A>::value << "\n";
std::cout << has_size<std::vector<int>>::value << "\n";
}
but you have to be careful, this does neither work when size is overloaded, nor when it is a template. When you can use C++11, you can replace the above sizeof trick by decltype magic

Function Composition in C++

There are a lot of impressive Boost libraries such as Boost.Lambda or Boost.Phoenix which go a long way towards making C++ into a truly functional language. But is there a straightforward way to create a composite function from any 2 or more arbitrary functions or functors?
If I have: int f(int x) and int g(int x), I want to do something like f . g which would statically generate a new function object equivalent to f(g(x)).
This seems to be possible through various techniques, such as those discussed here. Certainly, you can chain calls to boost::lambda::bind to create a composite functor. But is there anything in Boost which easily allows you to take any 2 or more functions or function objects and combine them to create a single composite functor, similar to how you would do it in a language like Haskell?
To anyone stumbling onto this page, there's a great blog post on this subject from bureau14:
http://blog.quasardb.net/function-composition-in-c11/
This takes advantage of the new features in C++ 11 as well as using boost.
Stumbling upon this question, I'd like to point out to anyone who comes across this today that this is possible with a relatively elegant syntax using just the standard library and a few helper classes thanks to decltype, auto, and perfect forwarding.
Defining these two classes:
template <class Arg, class ArgCall, class OuterCall>
class pipe {
private:
ArgCall argcall;
OuterCall outercall;
public:
typedef pipe<Arg, ArgCall, OuterCall> this_type;
pipe(ArgCall ac, OuterCall oc) : argcall(ac), outercall(oc) {}
auto operator()(Arg arg) -> decltype(outercall(argcall(arg))) {
return outercall(argcall(arg));
}
template <class NewCall>
pipe<Arg, this_type, NewCall> operator[](NewCall&& nc) {
return {*this, std::forward<NewCall>(nc)};
}
};
template <class Arg>
class pipe_source {
public:
typedef pipe_source<Arg> this_type;
Arg operator()(Arg arg) {
return arg;
}
template <class ArgCall, class OuterCall>
static pipe<Arg, ArgCall, OuterCall> create(ArgCall&& ac, OuterCall&& oc) {
return {std::forward<ArgCall>(ac), std::forward<OuterCall>(oc)};
}
template <class OuterCall>
pipe<Arg, this_type, OuterCall> operator[](OuterCall&& oc) {
return {*this, std::forward<OuterCall>(oc)};
}
};
A simple program:
int f(int x) {
return x*x;
}
int g(int x) {
return x-2;
}
int h(int x) {
return x/2;
}
int main() {
auto foo = pipe_source<int>::create(f, g);
//or:
auto bar = pipe_source<int>()[g][h];
std::cout << foo(10) << std::endl;
std::cout << bar(10) << std::endl;
return 0;
}
This has the added benefit that once it's in a pipe, as long as the return type is correct you can add another function f to the chain with pipe[f].
Then:
$ g++ test.cpp -o test -std=c++11
$ ./test
98
4
$
I don't know of anything that supports the syntax you wish for currently. However, it would be a simple matter to create one. Simply override * for functors (boost::function<> for example) so that it returns a composite functor.
template < typename R1, typename R2, typename T1, typename T2 >
boost::function<R1(T2)> operator * (boost::function<R1(T2)> const& f, boost::function<R2(T2)> const& g)
{
return boost::bind(f, boost::bind(g, _1));
}
Untested, but I suspect it's close if it doesn't work out of the box.
Template them.
template<typename T1> class FunctorOne {
FunctorOne(T1 newt)
: t(newt) {}
void operator()() {
t();
}
T1 t;
};
template<> class FunctorOne<void> {
void operator()() {
}
};
template<typename T1> class FunctorTwo {
FunctorOne(T1 newt)
: t(newt) {}
void operator()() {
t();
}
T1 t;
};
template<> class FunctorTwo<void> {
void operator()() {
}
};
FunctorOne<FunctorTwo<FunctorOne<FunctorTwo<void>>>>> strangefunctionobject(FunctorTwo(FunctorOne(FunctorTwo()));
Excellent use of typedefs is recommended.
Edit: Whoops. Turns out that type inference in constructors sucks. I'll get back in a minute with something that actually works :P
Even more edit:
If you wanted just functors rather than functionoids, you could just create a new instance, or even just use static functions.
template<typename T1, typename T2> class FunctorOne {
public:
static bool Call() {
T1::Call(T2::Call());
return true;
}
};
template<> class FunctorOne<void, void> {
public:
static bool Call() {
}
};
template<typename T1> class FunctorTwo {
public:
static bool Call() {
T1::Call();
}
};
template<> class FunctorTwo<void> {
public:
static bool Call() {
}
};
bool haicakes = FunctorOne<FunctorTwo<void>, FunctorTwo<void>>::Call();
This assumes that in any given function, you can handle each different signature somewhat manually. Use of decltype could help in this regard with a C++0x compiler.
C++11. No boost. No helper classes. Any amount of arguments. Just std::function and variadic templates.
template <typename F1, typename F2>
struct function_composition_traits : public function_composition_traits<decltype(&F1::operator()), decltype(&F2::operator())>
{};
template <typename ClassType1, typename ReturnType1, typename... Args1, typename ClassType2, typename ReturnType2, typename... Args2>
struct function_composition_traits<ReturnType1(ClassType1::*)(Args1...) const, ReturnType2(ClassType2::*)(Args2...) const>
{
typedef std::function<ReturnType2(Args1...)> composition;
template <typename Func1, typename Func2>
inline static composition compose(const Func1& f1, const Func2& f2) {
return [f1,f2](Args1... args) -> ReturnType2 { return f2(f1(std::forward<Args1>(args)...)); };
}
};
template <typename F1, typename F2>
typename function_composition_traits<F1,F2>::composition compose(const F1& lambda1,const F2& lambda2)
{
return function_composition_traits<F1,F2>::template compose<F1,F2>(lambda1, lambda2);
}
template <typename F, typename... Fs>
auto compose(F f, Fs... fs) -> decltype(compose(f, compose(fs...)))
{
return compose(f, compose(std::forward<Fs>(fs)...));
}
Usage:
auto add = [](int x, int y){ return x+y; };
auto mul = [](int x){ return x*2; };
auto divide = [](int x) { return (double)x / 3.0; };
auto test = compose(add, mul, divide);
cout << "Result: " << test(2,3);
Output:
Result: 3.33333
See this answer https://stackoverflow.com/a/27727236/286335.
Really short, easy and general.