I have a vector defined as:
std::vector<std::shared_ptr<Orders> > vOrders;
When adding to vOrders I want to add like:
vOrders.push_back(<std::shared_ptr<Orders> >([]() {
TimerForProcessingOrders _timerForProcessingOrders;
_timerForProcessingOrders.detach();
}));
but the compiler is giving me an error:
Expected expression: Expected '(' for function-style cast or type construction
It looks weird the < and > around std::shared_ptrbut removing it gives an error:
No matching conversion for functional-style cast from '<lambda >' to 'std::shared_ptr<Orders>'
What mistake am I making?
What this code does (in an ill formed way) is take the object constructed by the lambda, and store the lambda itself into the vector -- not an object of type shared_ptr<Order> which is what the vector requires.
but the compiler is giving me an error:
This is because the extra < > are completely invalid syntax, so the best the compiler can give you is "invalid expression".
It looks weird the < and > around std::shared_ptrbut removing it gives an error:
No matching conversion for functional-style cast from '<lambda >' to 'std::shared_ptr<Orders>'
Basically what you have here is shared_ptr<Orders>(/* .. Lambda .. */) -- and the compiler is saying that it has no idea how to turn the lambda into an Orders* to go into the shared_ptr.
What are you actually trying to accomplish here?
If you just want to transfer a pointer into the shared_ptr you can do something like
TimerForProcessingOrders _timerForProcessingOrders;
std::shared_ptr<Orders> ptr(_timerForProcessingOrders.detach());
vOrders.emplace_back(std::move(ptr));
no lambda is required.
What type is Orders? Actually, it doesn't really matter: the expression [](){ ... } certainly isn't of a type convertible to Orders*. ... and the angle brackets around the argument to push_back() a definitely wrong.
Did you mean to call the lambda expression?
vOrders.push_back(std::shared_ptr<Orders>([]() {
TimerForProcessingOrders _timerForProcessingOrders;
return _timerForProcessingOrders.detach();
})()
); // ^^ note these extra parenthesis
... but even that shouldn't work as the lambda expression doesn't return anything (hence the also added return).
Firstly, I'd suggest you follow Billy ONeals train of thought. But if you want to do it your way this is a SSCE of it.
There are two changes, this lambda returns an object and is executed, thereby returning.
#include <vector>
#include <memory>
#include <iostream>
struct Foo {
int val;
};
int main(int argc, char** argv) {
std::vector<std::shared_ptr<Foo> > v;
v.push_back([]() -> std::shared_ptr<Foo> { Foo f; f.val = 5; return std::make_shared<Foo>(f); }());
std::cout <<v[0]->val <<std::endl;
return 0;
}
Related
I'm using boost::bimap to map integers to strings:
typedef boost::bimap<int, std::string> ParamIDStrings;
typedef ParamIDStrings::value_type id_pair;
extern const ParamIDStrings paramIDStrings;
I'm trying to create reference variables so I can write code like:
paramIDStringsByID.at(5);
// Instead of having to remember which side is which:
paramIDStrings.left.at(5);
But I'm having a hard time interpreting the Boost documentation, to understand of what type bimap::left is.
I tried:
// Compiler throws error: invalid use of template-name 'boost::bimaps::bimap' without an argument list
boost::bimaps::bimap::left ¶mIDStringsByID = paramIDStrings.left;
// Compiler throws error: 'paramIDStrings' does not name a type
paramIDStrings::left_map ¶mIDStringsByID = paramIDStrings.left;
// Compiler throws error: invalid initialization of reference of type boost::bimaps::bimap<int, std::__cxx11::basic_string<char> >::left_map
boost::bimaps::bimap<int,std::string>::left_map &cParamIDStringsByID = cParamIDStrings.left;
You can use auto & to let the compiler do the work for you.
If you want to know the type that gets deduced you can use one of the tricks from here to make the compiler tell you.
boost/bimap/bimap.hpp has a typedef for this: left_map and right_map. So you can do:
paramIDStrings::left_map ¶mIDStringsByID = paramIDStrings.left;
this isn't quite working out. Let's see if we can collectively expand our knowledge on this one. Okay:
vector<vector<Point>> aVectorOfPoints
int main(){
someConstructor(&aVectorOfPoints)
}
someConstructor(vector<vector<Point>>* aVectorOfPoints){
functionOne(aVectorOfPOints);
}
functionOne(vector<vector<Point>>* aVectorOfPOints){
aVectorOfPoints[i][j] = getPointFromClass();
}
//functionX(...){...}
I'm getting some error underneath the assignment in functionOne. How can I better do this? Thanks.
The specific error is "No operator '=' matches these operands".
Why is this wrong?
aVectorOfPoints[i][j] = getPointFromClass();
type of aVectorOfPoints is vector<vector<Point>>*.
type of aVectorOfPoints[i] is vector<vector<Point>>.
type of aVectorOfPoints[i][j] is vector<Point>.
A Point cannot be assigned to a vector<Point>. Hence the compiler error.
Perhaps you meant to use:
(*aVectorOfPoints)[i][j] = getPointFromClass();
You can simplify the code by passing references.
int main(){
someConstructor(aVectorOfPoints)
}
someConstructor(vector<vector<Point>>& aVectorOfPoints){
functionOne(aVectorOfPOints);
}
functionOne(vector<vector<Point>>& aVectorOfPOints){
aVectorOfPoints[i][j] = getPointFromClass();
}
Use references instead of pointers:
someConstructor( vector<vector<Point>> &aVectorOfPoints) {
and the same for functionOne.
Your mistake is that aVectorOfPoints[i] indexes the pointer by i. If using pointers you'd need to dereference the pointer first before doing that, by writing (*aVectorOfPoints)[i][j].
I have some C++11 code using the auto inferred type that I have to convert to C++98. How would I go about converting the code, substituting in the actual type for all instances of auto?
It is going to be a PITA, but you can declare an incomplete struct template accepting a single type parameter.
Given the variable x you want to know the type of, you can use the struct with decltype(x) and that will lead to a compiler error that will show you the inferred type.
For example:
template<class Type> struct S;
int main() {
auto x = ...;
S<decltype(x)>();
}
Live demo
which will produce an error message in the form:
error: implicit instantiation of undefined template 'S<X>' (clang++)
error: invalid use of incomplete type 'struct S<X>' (g++)
with X being the inferred type. In this particular case the type is int.
Trivia: This has been recommended by Scott Meyer in one of the recent NDC 2014's videos (I don't remember which one).
As auto is known at compile-time, you need to interoperate with the compiler.
One option would be the Clang compiler's LibTooling library that provides infrastructure that you can base static analysis tools on.
For example, look at their refactoring example code that removes superfluous .c_str() calls from the code. I think you could write a similar tool that converts auto into the inferred type.
You can try to use the BOOST_AUTO macro in the Boost typeof library.
auto x = 5 + 7;
becomes
BOOST_AUTO(x,5+7);
You could use typeid and std::type_info::name();
#include <iostream>
#include <typeinfo>
#include <complex>
int
main()
{
using namespace std::literals::complex_literals;
auto x = 3.1415F;
std::cout << typeid(x).name() << '\n';
auto z = 1.0 + 1.0i;
std::cout << typeid(z).name() << '\n';
}
$ /home/ed/bin_concepts/bin/g++ -std=c++14 typeid.cpp
$ ./a.out
f
St7complexIdE
The names aren't beautiful but you can at least translate them.
These names are got from g++. The name is compiler dependent.
There is some movement to standardize a pretty_name().
Here is a non-standard way to unmangle the names.
An alternative approach would be to use function templates and type deduction. It may not work in all examples you have but it may help in some cases:
int foo ()
{
auto x = bar();
// do something with 'x'
}
Change this to:
template <typename T> int foo_(T x)
{
// do something with 'x'
}
int foo ()
{
foo_(bar());
}
auto is specified in terms of type deduction, so the above should have very similar, if not identical semantics as the C++ '11 version.
I know the following code does not work, and I fully understand why. What I actually do not understand is why not:
int main(int argc, char *argv[]) {
std::cout << (atoi(argv[1]) ? "foo" : 'b') << std::end;
}
Why: Of course, this expression may generate either a string or an integer, and this is the error pointed by the compiler:
error: operands to ?: have different types ‘const char*’ and ‘char’
Why not: Since the operator<< have a bind with both of the types const char* and char, why is it the compiler don't perform a code expansion as in a template -- which, I guess, is what is performed.
For example, if I had:
template <class T>
void a(const T& value) {
std::cout << a << std::endl;
}
I could call either a("foo") and a('b'), and -- I guess -- the compiler would do one expansion of the function with the type name [T = const char*] and another one with [T = char].
This may be a simple matter of what C++ does -- and what it does not --, but I fail to see if there's any corner case that would come up as an error if the expansion was performed.
C++ is a compiled statically-typed language and the type of an expression must be known at compile-time. The expression atoi(argv[1]) ? "foo" : 'b' could be a const char* or char, depending on the value of argv[1], which can't be known at compile-time. It's only when the program is actually executed that this value is known. So when the compiler is attempting to turn this expression into machine code, it can't decide which type to treat the expression as.
To see that it really doesn't have anything to do with the operator<<, just have the expression by itself:
int main(int argc, const char* argv[])
{
atoi(argv[1]) ? "foo" : 'b';
}
Even this won't compile, giving the following error:
error: operands to ?: have different types ‘const char*’ and ‘char’
It has nothing to do with cout or operator <<. The expression
atoi(argv[1]) ? "foo" : 'b'
itself wouldn't compile. The 2nd and 3rd operators that you feed to ?: must be either the same type, or types that are implicitly convertible to one other.
This is what you think you should be asking for:
#include <iostream>
#include <utility>
#include <type_traits>
#include <functional>
template<typename Left, typename Right>
auto tri( bool b, Left&& left, Right&& right )
-> decltype( std::forward<Left>(left)() )
{
if (b)
return std::forward<Left>(left)();
else
return std::forward<Right>(right)();
}
int main(int /*argc*/, char *argv[]) {
tri(
atoi(argv[1]),
[]()->std::ostream&{ return std::cout<<"foo"; },
[]()->std::ostream&{ return std::cout<<'b'; }
) << std::endl;
}
but it isn't what ? does.
C++ could be modified to do what you are asking, but the type cascade would grow boundlessly. Each time you have an expression that could return type A or type B, the calling code would have to be forked, which could cause further forking.
Signatures of functions would have to be expanded to list all of the types it "could" return.
Now, while this may be a worthwhile feature for C++ in the future, it isn't what C++ does now. Each expression in C++ has a single, definite type -- in template code, this occurs when you have instantiated the template.
As an aside, the ability to have poly-type return values in C++ would give you capabilities similar to exception handling, where a function could return a value or an error flag. As the calling code would have to automatically fork whenever you call a poly-type return value function, it would have to handle that error flag (either by returning it as an alternative type, or by handling it locally).
I have declared my array like this:
FT_Interface<4096> *to_make_ft[3] = { /* initialization with existing objects */ };
my interface is declared like this:
template<cyg_ucount32 S, int N>
class FT_Thread {
FT_Thread(FT_Interface<S> *entry[N]){}
};
And i call it (as expected with):
FT_Thread<4096, 3> ft(to_make_ft);
Yet it complains that the pointer has decayed.
ecos/install/include/ft/thread.hxx:70: error: incompatible types in assignment of ‘FT_Interface<4096u>**’ to ‘FT_Interface<4096u>* [3]’
Is there any way to prevent this from happening?
You need
FT_Thread(FT_Interface<S>* (&entry)[N]){}
// note these ^^-----^
With that, you get a reference to the array.
Edit: Of course, if you want a pointer to the array, you can have just that:
FT_Thread(FT_Interface<S>* (*entry)[N]){}
Though you need to call it with FT_Thread<4096,3> ft(&to_make_ft).
I don't know if this is right, but try changing
FT_Thread(FT_Interface<S> *entry[N]){}
to
FT_Thread(FT_Interface<S> (*entry[N])){}
I have a feeling that the compiler thinks that the * refers to the FT_Interface rather than the entry.