I'm using Visual Studio 2008 with the Boost v1.42.0 library. If I use an enum as the template argument, I get a compile error when adding a value using push_back(). The compiler error is: 'T': is not a legal base class and the location of the error is move.hpp line 79.
#include <boost/interprocess/containers/vector.hpp>
class Test {
public:
enum Types {
Unknown = 0,
First = 1,
Second = 2,
Third = 3
};
typedef boost::container::vector<Types> TypesVector;
};
int main() {
Test::TypesVector o;
o.push_back(Test::First);
return 0;
}
If I use a std::vector instead it works. And if I resize the Boost version first and then set the values using the [] operator it also works.
Is there some way to make this work using push_back()?
Template backtrace of the error:
error C2516: 'T' : is not a legal base class
1> main.cpp(21) : see declaration of 'T'
1> main.cpp(21) : see reference to class template instantiation 'boost::interprocess::rv' being compiled
1> with
1> [
1> T=Test::Types
1> ]
I think you have find really a bug. I have posted to the Boost ML to track the issue and try to have more info.
For the moment the single workaround I see is to specialize the rv class as follows, but I'm not sure this will work on all the cases.
namespace boost {
namespace interprocess {
template <>
class rv<Test::Types>
{
Test::Types v;
rv();
~rv();
rv(rv const&);
void operator=(rv const&);
operator Test::Types() const {return v;}
};
}}
If this do not works you can try using int instead of enum.
enum {
Unknown = 0,
First = 1,
Second = 2,
Third = 3
};
typedef int Types;
Of course this has the drawback to loss the enum safety.
It sounds like Boost has some erroneous logic to determine whether to derive from T or not.
Naively, one might assume that any type besides a native type or pointer may be used as a base. However enums are neither bases nor primitive. Perhaps they failed to account for that.
It looks like Boost is incorrectly determining that enums are compatible with its rvalue-reference emulation.
The best way to solve this is to avoid use of enums in Boost Interprocess structures.
A hack like
namespace boost {
namespace interprocess { // get inside boost
template<>
class is_movable<Test::Types> // add custom specialization of is_movable
: public ::boost::mpl::bool_<false>
{};
}}
might patch things up. Untested.
Add this right after your #includes so it appears before the first use.
Related
I have a project with quite a lot of function templates that I wrote back in Visual Studio 2017, and it always worked fine. Now I have to build it in VS2019, because I need to include the lib in another project that is written in VS2019, and the thing won't build.
There is one function template it seems to take issue with, although it doesn't actually complain about the function itself. The compiler just says "identifier not found" when I invoke it in the code. The thing is there in the namespace, however, even InteliSense sees it and links to it without complaining. Just the compiler won't.
Here's the code in question:
// declaration
namespace Oparse
{
// lots of other functions, many of them templates
template <typename T> OpModel<T> *_ModelPtr(T *receiver) { return new OpModel<T>(receiver); };
}
// Invocation
namespace Oparse
{
template <class T, class U>
class OpModelFactory
: public OpNestable
{
public:
OpModelFactory<T, U>(vector<U*> &receiver) : OpNestable(OP_MODELFACTORY), receiver(receiver) {};
// other stuff
void Serialize(string key, stringstream &stream, unsigned int indents)
{
for (unsigned int i = 0; i < receiver.size(); ++i)
{
// check if the instances are really of the type of this OpModel, otherwise there may be duplicates between polymorphic factories populating the same receiver.
T *currentModel = dynamic_cast<T*>(receiver[i]);
if (currentModel != NULL)
{
OpModel<T> *parser = _ModelPtr<T>(currentModel); // <-- identifier not found
parser->Serialize(key, stream, indents);
delete parser;
}
}
};
private:
vector<U*> &receiver;
}
}
If I comment that invocation, the project builds, despite there being a whole lot more function templates declared right where this one is. I have no clue what to do to make the linker find it. Are there any Visual Studio wizzards who could give me a hint? I must honestly confess that I haven't used the IDE in years, and it's my first time in Visual Studio 2019...
Here's the complete output of the error. There's a second message to it, but I found it perfectly unhelpful:
1>D:\Orbiter_installs\Orbiter2016\Orbitersdk\Oparse\include\OpModel.h(138,27): error C3861: '_ModelPtr': identifier not found
1>D:\Orbiter_installs\Orbiter2016\Orbitersdk\Oparse\include\OpModel.h(152): message : see reference to class template instantiation 'Oparse::OpModelFactory<T,U>' being compiled
And no, there's not further message attached. I have seen similar messages that usually go on with "with ... $further information", but this is all I get.
There is a circular dependency problem.
In Oparse.h, you first include OpModel.h that requires_ModelPtr in implementation of Serialize , but_ModelPtr is only defined later in the header.
You need to forward declare the template method.
In OpModel.h, write this instead:
namespace Oparse
{
template<typename T> class OpModel;
template <typename T> OpModel<T>* _ModelPtr(T* receiver);
// Remaining of OpModel.h...
typedef map<string, pair<Oparse::OpValue*, vector<Oparse::OpValidator*>>> OpModelDef;
typedef vector<pair<Oparse::OpValue*, vector<Oparse::OpValidator*>>> OpValues;
...
Note: I know this question was asked in different ways, but I couldn't solve it based on my restrictions:
I am using google test version 1.7
Compiling in Visual studio 2010, with platform toolset V100
I am writing google test for a library I have created.
In my library, I have 3 structs, as follows:
struct utc_clock{ .... }
struct system_clock {....}
struct cpu_clock {....}
moreover, I have another class that uses them as template parameters.
In my test case, I do as follows:
TEST(MyTest, testImportantThings)
{
time_point<utc_clock> tp = utc_clock::now();
ASSERT_EQ(..things with tp... );
... more ASSERTION
}
What I am trying to do, is to run
TEST(MyTest, testImportantThings)
multiple times for each of the utc_clock, system_clock, cpu_clock
I have looked into How to get gtest TYPED_TEST parameter type,
after that, I got the following:
template<typename T>
struct MyTest: public testing::Test{
using MyParamType = T;
};
using MyTypes = testing::TYpes<utc_clock, system_clock, cpu_clock>;
TYPED_TEST_CASE(MyTest, MyTypes);
TYPED_TEST(MyTest, testImportantStuff)
{
using clock = typename TestFixture::MyParamType;
timepoint<clock> tp = clock::now();
ASSERT_EQ(..things with tp... );
... more ASSERTION
}
But I get the following errors:
unexpected token(s) preceding ';' on: using MyParamType = T;
testing::internal::TYpeList use of class template requires template
arguement list online on: using MyTypes = testing::TYpes<utc_clock, system_clock, cpu_clock>;
and more...
It is possible that your compiler is too old to support defining type aliases with using. What if you replace those with old-style typedef statements?
For example, you could replace
using MyParamType = T;
With the equivalent:
typedef T MyParamType;
I have some C++ code I'm trying to compile in Visual Studio 2013, but I'm running into an error. Here's a simplified testcase that demonstrates the problem:
template <typename SomeEnum>
struct Inner {
SomeEnum variant;
int innerVal;
};
template <typename SomeEnum>
struct Outer {
int outerVal;
union {
Inner<SomeEnum> inners[10];
unsigned char data[20];
};
};
enum MyEnum {
VAR1,
VAR2
};
int main() {
Outer<MyEnum> outer;
return 0;
}
This gives me the error main.cpp(11): error C2621: 'Outer<MyEnum>::inners' : illegal union member; type 'Inner<SomeEnum>' has a copy constructor. It seems like Inner<SomeEnum> should be as POD as they come. Is this a known problem, or is the code invalid for a reason of which I'm not aware? Some Googling yielded no results on the issue.
The example compiles if I either Inner not a template class or if inners is not an array, but unfortunately neither of those is an option for my actual code. Are there any other ways I could accomplish the same thing?
It works on ideone.com, leading me to think it may be a VS2013 bug. You could try VS2015 if you can.
A possible workaround is to explicitly specialize for each enum you want to use.
Adding this after the MyEnum definition:
template <>
struct Inner<MyEnum> {
MyEnum variant;
int innerVal;
}
Makes the error go away for some reason. Obviously that will lead to a ton of duplicated code, which is what templates are trying to stop. You could possibly write a macro (ugh) to make this template specialization for you.
Embarrassingly simple problem here. I am trying to use std::array and am tripping at the first hurdle with the error ...
implicit instantiation of undefined template 'std::__1::array<char,10>'
The code that gives the error is shown below. I can work around it with std::map for now, but I'm sure the fix must be simple!!
enum p_t {
EMPTY = 0
,BORDER_L
// ...
,BORDER_BR
,DATUM
,NUMEL };
class PlotChars
{
array<char, p_t::NUMEL> charContainer;
// error on this ^ line:
// implicit instantiation of undefined template 'std::__1::array<char,10>'
};
My first guess would be that you simply forgot to:
#include <array>
...before trying to use the array template. While you can (at least indirectly) use a few classes without including the headers (e.g., the compiler can create an std::initializer_list from something like {1, 2, 3} without your including any headers) in most cases (including std::array) you need to include the header before using the class template.
You are using a C-style enum, so you probably need to omit the enum name, if your compiler isn't fully C++11 compliant.
array<char, NUMEL> charContainer;
This works on gcc 4.4.3, whereas the equivalent to your code does not yet work on that version (but does on later ones)
#include <array>
enum XX { X,Y,Z };
struct Foo
{
std::array<char, Y> a;
};
int main()
{
Foo f;
}
Try with that
std::array<char, (int)NUMEL> charContainer;
We've written a smart pointer class and have been using it with great success with the built-in Visual Studio STL implementation.
The problem is we've realized our performance bottlenecks are in the STL library in code ported from Linux (where the STL is significantly faster the way we're using it). So I'm trying to link in STLPort to see if it deals with our performance problems.
When using STLPort 5.2.1 however I get very strange build errors related to ambigous copy constructors. I've stripped it down to a 50 line C++ program
#include "stdafx.h"
#include <set>
using namespace std;
template<class T>
class CRefCountPtr
{
public:
CRefCountPtr(T* pT) : m_T(pT)
{
}
T** operator&()
{
return &m_T;
}
operator T*() const
{
return (T*)m_T;
}
bool operator< (T* pT) const
{
return m_T < pT;
}
T* m_T;
};
class Example
{
int example;
};
int _tmain(int argc, _TCHAR* argv[])
{
set< CRefCountPtr<Example> > blah;
Example ex;
blah.insert(&ex);
return 0;
}
The error I get back from VS2008SP1 is
stlport\stl\_tree.h(318) : error C2782: 'void stlp_std::_Copy_Construct(_Tp *,const _Tp &)' : template parameter '_Tp' is ambiguous
stlport\stl\_construct.h(130) : see declaration of 'stlp_std::_Copy_Construct'
could be 'CRefCountPtr<T>'
with
[
T=Example
]
or 'Example *'
.....
stlport_example.cpp(43) : see reference to class template instantiation 'stlp_std::set<_Key>' being compiled
with
[
_Key=CRefCountPtr<Example>
]
I'm kind of stuck at how to proceed here, anybody have any idea what's going on with this one?
It's actually your operator& that's causing ambiguity. In g++ the ambiguity is in destruct rather than construct but I assume it's a similar problem.
The compiler tries to take the address of your T to construct/destruct it, and gets back a T** instead of a CRefCountPtr<T>*, causing confusion.
I bet you could create your own specific allocator that knows how to deal with this (aka not a template) and get it to compile.
Probably better long term is to get rid of the operator& as it'll only cause confusion.