Google Test and boost::variant - boost

I wish to iterate over the types in my boost::variant within my unit test. This can be done as follows:
TEST_F (MyTest, testExucutedForIntsOnly)
{
typedef boost::variant<int, char, bool, double> var;
boost::mpl::for_each<SyntaxTree::Command::types>(function());
...
}
Where function is a functor. I simply want to ensure that a particular operation occurs differently for one type in the variant with respect to all others. However, I don't like that the test is now done in another function -- and what if I wish to access members for MyTest from the functor? It seems really messy.
Any suggestions on a better approach?

So, you want to call a function on a boost::variant that is type-dependent?
Try this:
template<typename T>
struct RunOnlyOnType_Helper
{
std::function<void(T)> func;
template<typename U>
void operator()( U unused ) {}
void operator()( T t ) { func(t); }
RunOnlyOnType_Helper(std::function<void(T)> func_):func(func_){}
};
template<typename T, typename Variant>
void RunOnlyOnType( Variant v, std::function< void(T) > func )
{
boost::apply_visitor( RunOnlyOnType_Helper<T>(func), v );
}
The idea is that RunOnlyOnType is a function that takes a variant and a functor on a particular type from the variant, and executes the functor if and only if the type of the variant matches the functor.
Then you can do this:
typedef boost::variant<int, char, bool, double> var;
var v(int(7)); // create a variant which is an int that has value 7
std::string bob = "you fool!\n";
RunOnlyOnType<int>( v, [&](int value)->void
{
// code goes here, and it can see variables from enclosing scope
// the value of v as an int is passed in as the argument value
std::cout << "V is an int with value " << value << " and bob says " << bob;
});
Is that what you want?
Disclaimer: I have never touched boost::variant before, the above has not been compiled, and this is based off of quickly reading the boost docs. In addition, the use of std::function above is sub-optimal (you should be able to use templated functors all the way down -- heck, you can probably extract the type T from the type signature of the functor).

Related

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)

Short circuit dispatching and stop condition in a string-literal to type matcher

I am playing with some piece of code, taken from Avoid if-else branching in string to type dispatching answer from Vittorio Romeo, but rewritten to use with C++14 cause Vittorios version uses C++17 fold expressions. I also thought the rewrite would be a good exercise.
Here is the code:
#include <type_traits>
#include <iostream>
#include <utility>
#include <string>
template<char... Cs>
using ct_str = std::integer_sequence<char, Cs...>;
template<typename T, T... Cs>
constexpr ct_str<Cs...> operator""_cs() { return {}; }
template<typename Name, typename T>
struct named_type
{
using name = Name;
using type = T;
};
template<typename... Ts>
struct named_type_list { };
using my_types = named_type_list<
named_type<decltype("int"_cs), int>,
named_type<decltype("bool"_cs), bool>,
named_type<decltype("long"_cs), long>,
named_type<decltype("float"_cs), float>,
named_type<decltype("double"_cs), double>,
named_type<decltype("string"_cs), std::string>
>;
template<std::size_t... Is, char... Cs>
constexpr bool same_impl(const std::string& s,
std::integer_sequence<char, Cs...>,
std::index_sequence<Is...>)
{
const char c_arr[] = {Cs...};
for (std::size_t i = 0; i != sizeof...(Cs); ++i) {
if (s[i] != c_arr[i]) return false;
}
return true;
//Original C++17 (fold expression)
//return ((s[Is] == Cs) && ...);
}
template<char... Cs>
constexpr bool same(const std::string& s, std::integer_sequence<char, Cs...> seq)
{
std::cout << "checking '" << s << "' against '";
std::initializer_list<bool>{ bool(std::cout << Cs)... };
std::cout << "'\n";
return s.size() >= sizeof...(Cs)
&& same_impl(s, seq, std::make_index_sequence<sizeof...(Cs)>{});
}
template<typename... Ts, typename F>
void handle(named_type_list<Ts...>, const std::string& input, F&& f)
{
using expand_type = int[];
expand_type{ 0, (same(input, typename Ts::name{}) && (f(Ts{}), false), 0)... };
//(void)std::initializer_list<int> {
// ( (same(input, typename Ts::name{}) && (f(Ts{}), false) ), 0)...
//};
//Original C++17 (fold expression)
//( (same(input, typename Ts::name{}) && (f(Ts{}), true) ) || ...);
}
int main(int argc, char** argv)
{
const std::string input{"float"};
handle(my_types{}, input, [](auto t)
{
std::cout << typeid(typename decltype(t)::type).name() << "\n";
// TEST: define std::vector with value_type (matched type "float") and add a few values
using mtype = typename decltype(t)::type;
std::vector<mtype> x;
x.push_back(2.2); // <-- does not compile
});
return 0;
}
I assume problem lies in the handle function that seems not to stop the evaluation properly. It should stop at the first invocation of f() in case of a match. Instead, it executes f() in case of a match as expected, but continues executing the remaining types in the named_type_list.
The current code results in this output:
checking 'float' against 'int'
checking 'float' against 'bool'
checking 'float' against 'long'
checking 'float' against 'float'
f
checking 'float' against 'double'
checking 'float' against 'string'
Actually I have no clue how to get that fixed. I tried to rewrite the C++17 fold expression using the std::initializer_list trick and also tried to use an expander (the uncommented part in the handle body. So I guess it is the expression itself not working properly.
Unfortunately I am out of ideas whats really happening at this point, also the fact that I am not experienced with Meta-Programming/Compile-time evaluation.
Another problem arises with an possible use of this code:
My use case would be in an XML property reader where I have type/value tags, e.g. <attribute type="double" value="2.5"/>, applying something like the handle function to get the typename from the type attribute value. That type I could use to further process the value.
For this I added within the handle f()-body in main() 3 lines, defining an std::vector with the found type and trying to add a value to it. This code does not compile, g++ responds with
error: no matching function for call to ‘std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > >::push_back(double)’
I guess this is the mixup out of compile-time and run-time behaviour and it does not work this way and that makes me curious how I could further process/use the matched type.
Thanks for your time on explanation, any help is greatly appreciated!
||, of course, short-circuits. Your version doesn't. I don't see short-circuiting as essential to correctness here, but if you want, it's easily implemented with an additional bool:
bool found = false;
expand_type{ 0, (!found &&
same(input, typename Ts::name{}) &&
(f(Ts{}), found = true), 0)... };
The second problem is because your handler function must be validly callable for every possible type in the type list, but you can't push_back 2.2 into a std::vector<std::string>. As an example, you might have something that obtains the value as a string, and the handler body could lexical_cast it to mtype.

C++11: Variadic template deduction logic

I have the following construct:
template <class... Args>
class some_class
{
public:
some_class() = default;
some_class(Args...) = delete;
~some_class() = default;
};
template<>
class some_class<void>
{
public:
some_class() = default;
~some_class() = default;
};
The reason for this is that I just want to allow the users to create objects using the default constructor, so for example:
some_class<int,float> b;
should work but
some_class<int,float> c(1,3.4);
should give me a compilation error.
At some point in time I also needed to create templates based on void hence, the specialization for void:
some_class<void> a;
But by mistake I have typed:
some_class<> d;
And suddenly my code stopped compiling and it gave me the error:
some_class<Args>::some_class(Args ...) [with Args = {}]’ cannot be
overloaded
some_class(Args...) = delete;
So here comes the question: I feel that I am wrong that I assume that some_class<> should be deduced to the void specialization... I just don't know why. Can please someone explain why some_class<> (ie: empty argument list) is different from some_class<void>? (A few lines from the standard will do :) )
https://ideone.com/o6u0D6
void is a type like any other (an incomplete type, to be precise). This means it can be used as a template argument for type template parameters normally. Taking your class template, these are all perfectly valid, and distinct, instantiations:
some_class<void>
some_class<void, void>
some_class<void, void, void>
some_class<void, char, void>
In the first case, the parameter pack Args has one element: void. In the second case, it has two elements: void and void. And so on.
This is quite different from the case some_class<>, in which case the parameter pack has zero elements. You can easily demonstrate this using sizeof...:
template <class... Pack>
struct Sizer
{
static constexpr size_t size = sizeof...(Pack);
};
int main()
{
std::cout << Sizer<>::size << ' ' << Sizer<void>::size << ' ' << Sizer<void, void>::size << std::endl;
}
This will output:
0 1 2
[Live example]
I can't really think of a relevant part of the standard to quote. Perhaps this (C++11 [temp.variadic] 14.5.3/1):
A template parameter pack is a template parameter that accepts zero or more template arguments. [ Example:
template<class ... Types> struct Tuple { };
Tuple<> t0; // Types contains no arguments
Tuple<int> t1; // Types contains one argument: int
Tuple<int, float> t2; // Types contains two arguments: int and float
Tuple<0> error; // error: 0 is not a type
—end example ]

casting void* to std::function

I have an issue. I'm trying to convert a void* to std::function.
This is just a simple example, any suggestions will be appreciated
#.h file
class Example {
public:
Example();
int foo(void* hi);
int fooFunc(std::function<int(int, int)> const& arg, int x, int y) {
foo(arg.target<void*>(), x, y);
return 2;
}
};
#.cpp file
Example::Example() {
}
int Example::foo(void * func, int x, int y)
{
//cast back to std::function
func(x, y);
std::cout << "running in foo: " << a << "\n";
return a;
}
Every casting i tried did not work.
I know i can send a std::function in this example, but it's for something bigger and i'm working on an example to make it work here.
The whole meaning of void*, is for sometimes to use it, in these situations, when you don't know what you will receive, and then cast it to the specific usage you need.
Thanks!
You can't.
You can cast a data pointer to void* and then back to the same pointer type you have started with. std::function is not a pointer type, so the cast is statically invalid, and it's not the same thing you have started with. You have started with a .target of type void(*)() but it's not a data pointer, it's a function pointer, so casting it to void* and back is implementation-defined.
You can:
Ignore the issue and cast to void(*)() anyway. Will work on most (but not all) platforms.
Use void(*)() instead of void* as a universal function pointer (you can cast it to other function types).
Use whatever tools C++ offers to avoid the cast altogether.

c++11 std::function like functors incomplete type

I've stumbled upon something I can't get through since last week...
Having this:
template<typename> struct fx;
template<typename R, typename...Args>
struct fx<R(Args...)>
{
virtual R operator()(const Args & ...x) const = 0;
};
and this:
template<typename> struct fx_err;
// I feel here something is wrong, but I can't figure it out.
template<template<typename> class F, typename R, typename... Args>
struct fx_err< F<R(Args...)> > : fx<R(R,Args...)>
{
using fx_type = F<R(Args...)>;
fx_type f;
R operator ()(const R &y, const Args & ...x) const override
{
return y - f(x...);
}
};
and this:
struct example_fun : fx<int(int,int,int)>
{
int operator() (const int &a, const int &b, const int &c) const override
{
return a * b * c;
}
};
when finally I try to use it like:
fx_err<example_fun> example;
int err = example(24,2,3,4);
compiler throws error: 'example has incomplete type'.
Something similar works only if I do not specialize fx_err and use pointer to fx_type functor instead, but then I need to add constructor to grab the pointer itself which is not something I want.
It's very frustrating. What's wrong with this? Is it possible what I'm trying to achieve? Can anybody help?
Thanks in advance.
UPDATE:
here's example code to play around with for those willing to experiment with this example: http://pastebin.com/i3bRF8tB
The problem on line:
fx_err<example_fun> example;
is caused by the fact that example_fun is "passed" to fx_err, which selects the declaration:
template<typename> struct fx_err;
which is an incomplete type.
The specialization you provide:
// I feel here something is wrong, but I can't figure it out.
template<template<typename> class F, typename R, typename... Args>
struct fx_err< F<R(Args...)> > : fx<R(R,Args...)>
{ ... }
cannot be selected, because example_fun is not a template class as required by:
template<typename> class F
Avoid template template parameters if you can. They add more complexity, and less flexibility, than you probably want.
It looks like you're trying to match the form of the fx base class against its derived class. Partial specialization requires exact matches, it won't slice to the base class. And even if it did, this member would be of abstract class type:
using fx_type = F<R(Args...)>;
fx_type f; // same as fx<R(Args...)> which is abstract
The solution is to preserve the derived class, and tell the partial specialization how to find the base. Then the partial specialization can do pattern matching on the base class.
template<typename derived, typename base = typename derived::fx>
struct fx_err;
template<typename derived, template<typename> class F, typename R, typename... Args>
struct fx_err< derived, F<R(Args...)> > : F<R(R,Args...)>
Live solution: http://coliru.stacked-crooked.com/a/870172bcad0a9034
Of course, finding the base class by typename derived::fx sort-of begs the question of what base class template was used. In theory, you could have several templates of the same name, or derived could have a member typedef my_base fx; instead of inheriting from an fx specialization.
More likely, though, you don't need template<typename> class F at all.
template<typename derived, typename base = typename derived::fx>
struct fx_err;
template<typename derived, typename R, typename... Args>
struct fx_err< derived, fx<R(Args...)> > : fx<R(R,Args...)>
fx_err<example_fun> does not match your partial specialization because example_fun is not of the form F<R(Args...)>. It inherits a type of that form, but that's not the same thing.
When selecting specializations for class templates, implicit conversions aren't considered. Therefore example_fun isn't seen as a fx<...> by the compiler when matching the specializations and the primary (undefined) template is chosen over the other specialization.
To solve this you can expose an alias for the base class in the derived class:
struct example_fun : fx<int(int,int,int)>
{
using type = fx<int(int,int,int)>;
};
And now use this alias at the declaration site:
fx_err<example_fun::type> example;
int err = example(24,2,3,4);
You can even use a macro to avoid repeating the base class name:
template<class T> struct tag { using type = T; };
#define BASE_TAG(B) B, public tag<B>
struct example_fun : BASE_TAG(fx<int(int, int, int)>) {
// ...
};
Your basic problem is that template type pattern matching does not work like function overload template pattern matching. Inheritance is ignored, only the type passed in is pattern matched against.
So struct foo: some_template<some_args...> does not match some_template<some_args...> during template type pattern matching for the purpose of figuring out which specialization to use.
This lets us work with types as values in functions:
template<class T>struct tag{using type=T;};
template<class Tag>using type_t=typename Tag::type;
Now function template pattern matching works more like what you seem to be expecting:
template<template<class...>class Z, class...Args>
constexpr tag<Z<Args...>> get_template( Z<Args...>const& ) { return {}; }
takes a single argument, does template function pattern matching and deduction against it. This will look at parents of the type passed in. It tries to match Z<Args...> for some template Z.
It returns a tag<Z<Args...>>, which is a stateless type that just stores the type we need. We can then feed the above through an alias to extract that template expansion:
template<class T>
using get_template_t = type_t<decltype(get_template(std::declval<T>()))>;
which is most of the way there.
Next, we need some SFINAE helper magic:
template<class...>struct voider:tag<void>{};
template<class...Ts>using void_t=type_t<voider<Ts...>>;
std::void_t is C++14, and takes a bunch of types and throws them away, returning void instead. I do it in 2 lines because some compilers fail on the one-line version.
Ok, now we attack fx_err:
template<class,class=void> struct fx_err;
the second class=void lets us do FSINAE work. We start with your
template<template<class...>class F, class R, class...Args>
struct fx_err< F<R(Args...)>, void > : fx<R(R,Args...)>
{
using fx_type = F<R(Args...)>;
fx_type f;
R operator ()(const R &y, const Args & ...x) const override {
return y - f(x...);
}
};
and we also do this:
template<class T>
struct fx_err< T, void_t<get_template_t<T>>> : fx_err<get_template_t<T>>
{};
which I think should work. If it doesn't, we just need to add a test to exclude the direct T<F(Args...)> case from this specialization.

Resources