I've got the following class definition:
class Portal
{
public:
Portal( const vector<vec3> &vertices, shared_ptr<Sector> target );
...
};
Somewhere else, I want to create an instanceof said class like this:
auto portal = make_shared<Portal>( portalVertices, target );
However, I get the following error message in Visual Studio 2010:
error C2668: 'boost::make_shared' : ambiguous call to overloaded
function
Can anyone tell me why? I only define a single constructor. Thank you!
As you are using the keyword auto I assume you are using C++11 features.
C++11 also comes with std::make_shared.
So, please try adding the namespace:
auto portal = std::make_shared<Portal>( portalVertices, target );
or
auto portal = boost::make_shared<Portal>( portalVertices, target );
So what I usually do in my code / the .C file is:
using namespace std; // this is a "using" directive
....
void somefunction() {
auto portal = make_shared<Portal>( ... );
}
As you mentioned you were specifying in your header
using boost::make_shared;
I would really like to see the full header file. As I think you actually wanted to have a using directive, but ended up in having a using declaration.
Have a look at this description:
using directive: http://msdn.microsoft.com/en-us/library/aewtdfs3%28v=vs.80%29.aspx
using declaration: http://msdn.microsoft.com/en-us/library/was37tzw%28v=vs.80%29.aspx
Related
On Ubuntu 20.04, ROS2 Foxy, GCC version 9.4.0, C++ rclcpp node.
The completely undocumented builder pattern for messages works as follows. (Odometry for example)
#include <nav_msgs/msg/odometry.hpp>
// https://docs.ros2.org/foxy/api/nav_msgs/msg/Odometry.html
nav_msgs::msg::Odometry const odom = nav_msgs::build<nav_msgs::msg::Odometry>()
.header(std_msgs::msg::Header()) .child_frame_id("")
.pose(geometry_msgs::msg::PoseWithCovariance())
.twist(geometry_msgs::msg::TwistWithCovariance());
// This works // Excuse typos
This is opposed to the "classic" style (since ROS committee won't allow initialization with arguments):
nav_msgs::msg::Odometry odom; // Notice can't make it const
odom.header = std_msgs::msg::Header();
odom.header.stamp = builtin_interfaces::msg::Time(); // or = node.get_clock()->now();
odom.header.frame_id = "...";
// ... etc, fill in other odometry members
Problem: But a lot of the time I get a cryptic error, and I can't discern why.
Ex, if I tried:
odom.header = std_msgs::build<std_msgs::msg::Header>() // Error here, on ')'
.stamp(node.get_clock()->now()).frame_id("map");
error: use of auto std_msgs::build() [with MessageType = std_msgs::msg::Header_<std::allocator<void> >] before deduction of auto
I tried to make the type as explicit as possible; casting to target type, creating an intermediary variable of the target type, no change in error.
To even understand that the builder pattern exists, unless you found some cryptic scrawl on the internet (like so), you have to dig into the generated header files, so I did.
You will find
/// vim /opt/ros/foxy/include/std_msgs/msg/header.hpp
// generated from rosidl_generator_cpp/resource/idl.hpp.em
// generated code does not contain a copyright notice
#ifndef STD_MSGS__MSG__HEADER_HPP_
#define STD_MSGS__MSG__HEADER_HPP_
#include "std_msgs/msg/detail/header__struct.hpp"
#include "std_msgs/msg/detail/header__builder.hpp"
#include "std_msgs/msg/detail/header__traits.hpp"
#endif // STD_MSGS__MSG__HEADER_HPP_
/// vim /opt/ros/foxy/include/std_msgs/msg/detail/header__builder.hpp
// ...
namespace std_msgs {
namespace msg {
namespace builder {
// ... bunch of builder classes calling the next, ex:
class Init_Header_stamp { ... };
} // namespace builder
} // namespace msg
template<typename MessageType>
auto build();
template<>
inline
auto build<::std_msgs::msg::Header>()
{
return std_msgs::msg::builder::Init_Header_stamp();
}
} // namespace std_msgs
Using this as a guide, I wondered if I repeated / copy-pasted the template declaration in my code, and replaced auto with the actual type(s), would that work... but at this point my c++ fu was exhausted, and all the cobbled substitutions just gave more weird errors.
Thoughts?
Solution:
The parent type includes the child type definitions, but not the builder definitions.
In this example, to include Odometry and then use the builder pattern on Header, you also need to #include <std_msgs/msg/header.hpp>.
Why: (no, really, why was it implemented like this, where is the documentation)
/// In vim /opt/ros/foxy/include/nav_msgs/msg/detail/odometry__struct.hpp
// Include directives for member types
// Member 'header'
#include "std_msgs/msg/detail/header__struct.hpp"
// Member 'pose'
#include "geometry_msgs/msg/detail/pose_with_covariance__struct.hpp"
// Member 'twist'
#include "geometry_msgs/msg/detail/twist_with_covariance__struct.hpp"
/// Notice, doesn't include the full child header, which also includes __builder.hpp,
/// but just the sub-header with type definitions, __struct.hpp!
So include every header manually if you use it's builder pattern.
I am developing a library which lets user set a crucial type alias, or do it through preprocessor directives.
This type alias (or the directive) is undeclared in the library, by design. Thus, when developing my code I get annoying error messages and squiggles for this undeclared type. This could be avoided if I declare a temporary type for it somewhere. However, I do not like the idea of declaring it when I work with the code and then remove it when I publish it. It is also bug prone, since I could easily forget to remove it.
My question is: Can I define preprocessor directives for VS Code's static analysis (IntelliSense? C/C++ Extension)?
That would let me consider the analysis like what a well defined type alias would produce. And avoid annoying error messages/squiggles.
Minimal reproducable example:
Online compiler example
tCore.hpp
#pragma once
#include <string>
// User is responsible of declaring the tCore type
// tCore interface methods
template<typename TCore>
std::string printImpl();
tPrint.hpp
#pragma once
#include <iostream>
class tPrint {
public:
tPrint() = default;
void print() const {
std::cout << printImpl<tCore>() << std::endl; // <-- Static analysis error here!
}
};
tFoo.hpp - tCore candidate
#pragma once
#include <string>
#include "tCore.hpp"
struct tFoo {};
template<>
std::string printImpl<tFoo>() {
return "tFoo";
}
main.cpp
#include <tFoo.hpp>
using tCore = tFoo;
int main() {
tPrint p{};
p.print(); // -> "tFoo"
return 0;
}
I found out it was IntelliSense causing the error through the C/C++ Extension.
I also found an option of adding compiler arguments to IntelliSense, which is exactly what I was looking for.
Either through the UI:
Press
F1 -> > C/C++: Edit Configurations (UI) -> Scroll down to Defines
Or via the JSON :
c_cpp_properties.json configurations has a field defines which holds any compiler arguments.
[Edited to provide a minimal set to reproduce the issue.]
I have C++ code similar to this (file.h):
namespace xxx {
template< typename T >
class Array {};
using sint = std::ptrdiff_t;
using uint = std::size_t;
using dfloat = double;
using IntegerArray = Array< xxx::sint >;
using UnsignedArray = Array< xxx::uint >;
using FloatArray = Array< xxx::dfloat >;
}
/// \brief A namespace
namespace yyy {
namespace {
/// \brief A function
inline out* function( xxx::UnsignedArray const& in ) {}
/// \brief A function
inline out* function( xxx::IntegerArray const& in ) {}
/// \brief A function
inline out* function( xxx::FloatArray const& in ) {}
/// \brief A class
class AAA {
public:
/// \brief A class method
out* function( xxx::BBB const& bbb ) {}
};
}}
The Doxyfile is:
OUTPUT_DIRECTORY = out
EXTRACT_ANON_NSPACES = YES
INPUT = .
FILE_PATTERNS = *.h
Doxygen complains with:
Searching for member function documentation...
/Users/cris/tmp/doxygenissue/file.h:25: warning: no matching class member found for
out *anonymous_namespace file yyy::anonymous_namespace{file.h}::yyy::h::function(xxx::IntegerArray const &in)
/Users/cris/tmp/doxygenissue/file.h:28: warning: no matching class member found for
out *anonymous_namespace file yyy::anonymous_namespace{file.h}::yyy::h::function(xxx::FloatArray const &in)
It doesn't seem to see the 2nd and 3rd functions. Only the first one shows up in the documentation. The anonymous namespace is needed to generate this error, as is the class with a method with the identical name.
Does anybody know a workaround? Besides changing the name of the class method, that is...
I found a rather ugly way to make it work until the bug gets fixed in Doxygen. It seems to work at least for my case. I suppose it affects some links, though, but at this point I think I prefer to get the expected description for each function than having proper links and namespace names.
I thought about the fact that Doxygen accepts preprocessor options which can be used to add a Doxygen specific #define. Here is my doxygen.h header:
#ifndef DOXYGEN_HPP
#define DOXYGEN_HPP
#ifdef DOXYGEN
#define no_name doxygen
#else
#define no_name
#endif
#endif
As we can see, I defined a macro named no_name and when I compile with Doxygen I set it to doxygen otherwise it remains empty.
Now in my C++ files I do:
...
namespace no_name
{
// static code goes here
...
} // no name namespace
...
So now when compiling with g++, I don't get a name as expected. When compiling with Doxygen, however, the namespace is given a name: doxygen and I do not get that error anymore.
For this magic to work, you also need to tweak your doxy file. Here are the relevant options:
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = DOXYGEN=1
EXPAND_AS_DEFINED = no_name
You may also need to fix the include path. It will be very important that the doxygen.h file gets included. I have CMake so it's easy for me:
INCLUDE_PATH = #CMAKE_SOURCE_DIR#
At this point I've not seen anything breaking badly. So I am guessing it's a nice intermediate solution.
One other thing, make sure that INHERIT_DOCS is NO because by default it's YES and that means you'd still get the base class description.
As you are overloading a function, you should use /overload keyword , to add documentation for overloaded function.
template<typename T> class Array;
using UnsignedArray = Array<unsigned>
using IntegerArray = Array<int>
using FloatArray = Array<float>
/// \overload brief A function
void function(UnsignedArray const&);
/// \overload brief A function
void function(IntegerArray const&);
/// \overload brief A function
void function(FloatArray const&);
This will help doxygen to separately document them
I'm working on a project in c++ and I stuck with no idea what is wrong. I've writen 4 classes and everything looked fine during work (under visual studio 2010). VS 'saw' all the definition, i could use auto-fill and sudgestions, but when I tried to compile the project it sudennly went blind. It's like I didnt include headers or something (which I did). The strange thing is there is no problem with working with those classes on VS (i can ctrl+space for hint, list of attributes and methods and all that stuff) but when i try to compile it says "ClassName" is not a type.
Quick sample of problem below:
ProButton.cpp:
#include "ProButton.h"
using namespace pGUI;
ProButton::ProButton( ... )
: ProControl( ... )
{
...
}
ProButton.h:
#ifndef __PRO_BUTTON__
#define __PRO_BUTTON__
#include <string>
#include "ProControl.h"
namespace pGUI
{
class ProButton :
public pGUI::ProControl
{
public:
//attributes
...
public:
//methods
...
};
}
#endif
but compiler says:
Error 291 error C2653: 'ProButton' : is not a class or namespace name
for this line in ProButton.cpp: ProButton::ProButton( ... )
It also says:
Error 23 error C2039: 'ProControl' : is not a member of 'pGUI'
Error 24 error C2504: 'ProControl' : base class undefined
and all similar errors for whole project. I have no idea what is wrong. Looks like my VS broke :D
Of course those (...) means there is code there, just not that important for now. I can upload all solution somewhere fi it will help.
edit//
About namespaces, all header files (classes declaration) are defined in namespace with:
namespace pGUI{
class ProClass
{
};
}
all definitions for these classes (in ProClass.cpp) are using:
using namespace pGUI;
at the beginning.
I think the problem is with order of including files.
Im not sure how this is supposed to be done. So far i have 4 classes that:
class ProGUI:
has a pointer to ProContainer
includes: ProContainer and ProControl
class ProContainer:
has pointers to: ProGUI and ProControl
class ProControl:
has a pointer to ProContainer
includes ProButton
is a base class for ProButton
class ProButton:
is a sub-class of ProControl
Those classes also uses irrlicht library and I'm not sure where to include it.
I had it included in my main file just before #include "ProGUI.h". This is also the only include in main. ProGUI.h .
//EDIT 2 -> solved
It was a problem with includes. I needed to rethink my inclusion order and add some forward declarations. Anyway that all seemed strange and took me a lot of time to figure i out. Thx for help. :)
It seems that you are using following statement:
using namespace pGUI;
Just before the class declaration:
class ProControl
{
};
Instead of using following approach:
namespace pGUI
{
class ProControl
{
};
}
The using namespace, as it says uses a namespace. You need to explicitly put something a namespace using namespace keyword followed by braces!
using namespace pGUI informs the compiler that it should look in the pGUI namespace to resolve existing names.
To declare or implement something in a namespace you need to be more specific. with either:
namespace pGUI
{
ProButton::ProButton( ... ) : ProControl( ... )
{
...
}
}
or:
pGUI::ProButton::ProButton( ... ) : ProControl( ... )
{
....
}
Personally, I consider any use of using namespace to be a lazy programmer hack that completely defeats the point of namespaces. But I digress. :)
Goal: To inherit from a class with 2 template parameters.
Error
Error error C2143: syntax error : missing ',' before '<'
The Code
template< typename Type >
class AssetManager : public IsDerivedFromBase< Type, Asset* >
{
// Class specific code here
};
Things you need to know: Asset is a class that just wraps a char* with a getter/setter and IsDerivedFromBase will be used to basically test wether or not Type is a derivative of Asset. These sets of classes are isolated in there own small scale visual Studio 2012 project and will be integrated into the main project once all the functionality has been tested thoroughly.
Some Edits based on Comments
Thank you for the help so far, I really appreciate it. Here are some more specifics:
IsDerivedFromBase.h
#ifndef ISDERIVEDFROMBASE_H
#define ISDERIVEDFROMBASE_H
#include< iostream > // For access to NULL
namespace Fenrir
{
template< typename Type, typename Base >
class IsDerivedFromBase
{
private:
static void Constraints( Type* _inheritedType )
{
Base* temp = NULL;
// Should throw compiler error if
// this assignment is not possible.
temp = _inheritedType;
}
protected:
IsDerivedFromBase( ) { void( *test )( Type* ) = Constraints; }
};
}
#endif
Note: This class was based off of a class I read about in an article. I have since found a better way to achieve the desired result; however, I wish to understand where this error is stemming from.
AssetManager.h"
#ifndef ASSETMANAGER_H
#define ASSETMANAGER_H
#include "IsDerivedFromBase.h"
namespace Fenrir
{
template< typename Type >
class AssetManager : public IsDerivedFromBase< Type, Asset* >
{
// Class specific code
};
}
#endif
Keeping class specific code to a minimum to keep this post as neat as possible, if more info is needed just let me know and I can add it in :).
That error message is common when the compiler encounters an identifier that it did not expect, so a first guess would be that IsDerivedFromBase is not known to the compiler at the time (maybe you did not include the appropriate header?). Alternatively, if IsDerivedFromBase is not a template, the compiler would also expect a , (or ;) after it.
Solved my issue which was interestingly silly. So due to a comment (from Jesse Good) I took a quick look at my includes. Since this was a small "whip it up quick" kind of project I didn't really pay much attention to them. I don't know exactly where the error was occuring, but I found out that AssetManager did not know about IsDerivedFromBase so I set up the following code block to just solve that issue without having to write a bunch of
#include statements everywhere!
// Contact point houses all of the include files
// for this project to keep everything in one place.
#ifndef CONTACTPOINT_H
#define CONTACTPOINT_H
#include "Asset.h"
#include "Sprite.h"
#include "IsDerivedFromBase.h"
#include "GenericManager.h"
#include "AssetManager.h"
#endif
Now I just include this in every header and all is well. I've been programming C++ for a little over a year now and never ran into this, a good lesson to learn for anyone new programming.
Thanks for your help everyone : )