I would like to store some closures in an array.
I tagged the question MSVC10 since it seems that according to c++11 closures should be compatible (at least under some conditions) with function pointers but MSVC10 does not supports that.
Is there a way around this limitation?
example:
typedef double (*Func)(const C* c);
struct Feature{
Feature(FeatureId i_id = None, const QString& i_name=QString(), Func i_ex = nullptr)
:id(i_id),name(i_name), extraction(i_ex)
{}
FeatureId id;
QString name;
Func extraction;
};
QList<Feature> features;
features.append(Feature(feat_t, "a/t", [](const C* c) -> double{return c->a.t;} ));
I want to be able to assign closures to the function pointer because i do not want to define dozens of separate functions.
Thanks in advance for your suggestions.
You should use std::function<double(const C*)> (see this) instead of Func, so
struct Feature{
FeatureId id;
QString name;
std::function<double(const C*)> extraction;
/// etc...
};
You may need to upgrade your compiler (I guess that Visual Studio 2010 appeared before the C++11 standard, but I never used Windows or other Microsoft products). Did you consider using a recent GCC (4.9 at least) or a recent Clang/LLVM (3.5) ?
If you cannot upgrade your compiler, stick to C++98 and don't use C++11 features.
By definition, a closure is more heavy that a function pointer, since it contains closed values (some of which might be hidden or non-obvious).
Related
I am implementing a command pattern implementations with large number of actions and parameters involved. To simplify I am planning to use class that can hold all possible params to module in a map.
class ParamBag {
public:
add(int paramId, shared_ptr<IParam> param);
bool contains(int paramId);
std::shared_ptr<IParam> get(paramId);
private:
int mask;
std::map<int, std::shared_ptr<IParam>> params;
};
One clear downside of this implementation is each param has to extend from IParam interface, can I somehow simplify this.
If the one that uses the param after the get knows the type of the param, then you can use c++17 std::any, or if you must use c++11 you can try boost::any, or if none of those you can resort back to a void*.
The difference is that void* will not fail on a cast to a wrong type, where any_cast would throw an exception, or return nullptr if used with a pointer. You would also need to use a custom deleter in the std::shared_ptr in order to be able to free the void*.
Supposing one needs to obtain a logical value based on a
pack of template parameters, is there a reason to prefer an alias approach
vs a function approach?
Example:
template<bool...> struct bool_pack;
template<bool... bs>
using all_true = std::is_same<bool_pack<bs..., true>,
bool_pack<true, bs...>>;
as opposed to
template<class none=void>
constexpr bool all_true() { return true; }
template<bool First, bool... Rest>
constexpr bool all_true() {
return First and all_true<Rest...>();
}
Time required for compiling your example implementations
... should be measured, of course. That said, I have seen micro-benchmarks where the std::is_same approach leads to significantly shorter compile times; even compared to the C++17 fold expression (true && ... && bs) with the respective compilers. The recursive "function approach" you gave as an example should be clearly inferior in compile-time performance.
Note, however, that one could surely offer the most convenient interface by providing a wrapper around the most "efficient" (regarding compile-time effort) implementation.
Convenience in using the "interface"
Given these two choices, I would prefer the alias approach. If you need the result of that helper as a type (for inheritance, template-metaprogramming with specializations, or for tag dispatch), the alias yields cleaner syntax compared to, say, std::bool_constant<all_true_v<some_condition(), some_other_condition()>()>. In the other direction, it is simple to obtain a value of type bool from the alias: all_true<some_condition(), some_other_condition()>{} (relying on implicit type conversion).
Since C++14, yet another (fancy?) choice is to provide a value by a constexpr variable template which has either type std::true_type or std::false_type. By implicit conversion to bool it can readily be used where plain true or false is required, but it can also be passed as a function argument without losing its compile-time guarantee.
template<bool... bs>
constexpr auto all_true_c = typename std::is_same<
bool_pack<true, bs...>, bool_pack<bs..., true>
>::type{};
It may be a good strategy to follow the naming conventions used in the <type_traits> header of modern C++ providing both forms. If some utility is supposed to provide a value, one finds helper variable templates such as std::is_same_v:
template<class T, class U>
inline constexpr bool is_same_v = is_same<T, U>::value;// (since C++17)
if some helper is supposed to provide a type, one finds helper types such as std::decay_t:
template<class T>
using decay_t = typename decay<T>::type;// (since C++14)
... in addition to the conventional utilities without suffix, respectively.
Referring to my previous question, as the explanation is required in detail.
How is the following code snippet working, fundamental and C++ 03 equivalent ?
auto get_option_name = [](const std::pair<const std::string, std::string>& p) -> const std::string& {
return p.first;
};
It's equivalent to:
class Extractor {
// Definition of "function call" operator, to use instance
// of this class like a function
const std::string& operator()(const std::pair<const std::string, std::string>& p) {
return p.first;
}
};
Extractor get_option_name;
More information on wikipedia or on stackoverflow
#Garf365's answer is the best. A lambda and a class like that one really are the most similar - you can use them just like callable functions, and pass around pointers and references to them.
However, you may also want to learn about using function templates to do this work during compile-time, especially when passing them as a parameter to another template, as in using the boost library.
I was curious if there was an improvement in the complexity of the code the compiler produced by using a function template, and there was!
Look for yourself:
Using a "function object" or "functor" class (or whatever they are called) - is 187 lines of assembly from GCC, and 237 lines of assembly from clang.
Using a function template - only 65 lines of assembly from GCC, and 84 from clang. That's a reduction by a factor of 300%!
Thank you for asking the question and leading me to look into it!
At my workplace, we changed string type (which holds internationalized characters) for from std::wstring to std::u16string after VS 2015(Update 3) compiler upgrade.
Due to this, we are seeing loads of performance regressions such as this.
The profiler analysis reveals that std::u16string's std::char_traits<char16_t> operations such as copy, compare, find and assign are the most hit and are taking longer than std::wstring's std::char_traits<wchar_t> counterparts.
These std::char_traits<wchar_t> operations are written in terms of std::wmem* and std::char_traits<char16_t> operations are written in terms of for loops.
If we change these traits operations for char16_t type (or std::u16string) to use our own customized traits, we are seeing performance improvements with performance comparable to std::wstring.
We are planning to write our own custom traits (until MS fixes it for next version of VS) as follows
struct string_custom_traits : public std::char_traits<char16_t>
{
static const char16_t * copy(char16_t* dest, const char16_t* src, size_t count)
{
return (count == 0 ? src : (char16_t*)std::memcpy(dest, src, count * sizeof(char16_t)));
}
};
Would that be OK? Are there any problems with this approach ?
The following code outputs different results on various compilers:
2,1,2 on Visual Studio 2013
2,2,2 on Visual Studio 2015
2,1,1 on GCC5/c++14
2,2,2 on Clang 3.7 with Microsoft Codegen
2,1,2 on Clang 3.6/c++11 under Ubuntu 14.04
Finally, how it should work according to C++ standard?
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std;
class Value;
using Array = std::vector<Value>;
class Value
{
public:
Value(const Array &)
{
}
Value(int)
{
}
};
void foo(Array const& a)
{
printf("%d\n", (int)a.size());
}
int main()
{
Array a1 = { 1, 2 };
foo(a1);
foo(Array{ a1 });
foo(Array({ a1 }));
}
P.S. The same issue reveals with json_spirit library from this article: http://www.codeproject.com/Articles/20027/JSON-Spirit-A-C-JSON-Parser-Generator-Implemented
Your program is ill-formed in C++11, as you have created a std::vector type with an incomplete type as an argument. The value type of a vector must be complete when you create the std::vector<T> type.
As an ill-formed program (and I'm not aware of a requirement for a diagnostic), any and all behavior is legal under the standard.
The requirement that vector's T be a complete type is probably over-specified (there is really no convincing reason to have that requirement), but it exists. Asking the same question in C++1z will lead to a different answer, as that requirement was relaxed.
Ignoring that issue, philosophically:
Array a1 = { 1, 2 };
this should generate a std::vector with two elements.
foo(a1);
This should pass a1 to foo, as the types match exactly.
foo(Array{ a1 });
Here we have {}. My rule of thumb with {} is "if it is non-empty, and it can match an initializer_list constructor, it must".
As a1 can be converted to a Value, Array{ a1 } is an array of one Value.
foo(Array({ a1 }));
Here we look at an argument of the constructor Array that can be called with { a1 }. Both the std::initalizer_list<Value> and the Array&& constructors can be.
Which is called should not matter: The Array&& constructor in turn sends the {a1} to the std::initalizer_list<Value> constructor.
So my opinion is that it should print 211. This is, however, merely an opinion on what the could ought to do, not an analysis of what the standard says it should do, as the C++11 standard quite clearly states your program is ill-formed.
On the other hand, hiding the copy constructor seems rude.
On the final hand, you did write a simply insane type. Insane behavior is to be expected.
A more practical concern might be when the Value type has a template constructor that happens to also match a std::vector<Value>.
In C++11, compilers' determination to match braced initializers with constructors taking std::initializer_lists is so strong, it prevails even if the best-match std::initializer_list constructor can't be called (Scott Meyers).
Array a1 = { 1, 2 }; // Call Initiliazer list constructor foo(a1); // print 2
foo(Array{ a1 }); // Call Initiliazer list constructor. Print 1
foo(Array({ a1 })); // Call Initiliazer list constructor. Print 1
According to the standard, the result must be: 2,1,1
Yakk's answer mention that the program is ill-formed in C++11. But this post is very interesting.