Inheriting from template class - c++

#include <iostream>
#include <math.h>
using namespace std;
template<template<short,short,short,int> class Derived>
struct AllocFactor_Core
{
private:
static long double factor_;
static long double calcFactor_(const short mantissa, const short exponent,const short base)
{
return mantissa * ::pow(static_cast<long double>(base),exponent);
}
public:
static const long double getFactor()
{
return factor_;
}
void setFactor(const short mantissa,const short exponent,const short base)
{
factor_ = calcFactor_(mantissa,exponent,base);
}
void setFactor(const long double factor)
{
factor_ = factor;
}
};
template<short Mantissa, short Exponent, short Base = 10, int Tag = 0>
struct AllocFactorScientific : private AllocFactor_Core<AllocFactorScientific>
{
static short base_;
using AllocFactor_Core<AllocFactorScientific<Mantissa,Exponent,Base,Tag>>::getFactor;
//I'm getting an error here saying: error: type/value mismatch at argument 1 in template
//parameter list for 'template<template<short int <anonymous>, short int <anonymous>, short int
// <anonymous>, int <anonymous> > class Derived> struct AllocFactor_Core'|
};
template<short Mantissa, short Exponent, short Base, int Tag>
short AllocFactorScientific<Mantissa, Exponent, Base,Tag>::base_ = Base;
Please see comment in code (3 lines above). Basically what happens is that if I have the AllocFactor_Core class as a regular non-template class and when with using directive I just provide name of this class followed by :: and fnc name it works, but as soon as I declare AllocFactor_Core as a template and I try to provide params for it I'm getting beforementioned error.

Your base class expects a template template parameter, but you are passing it a concrete class. Use e.g. the following instead:
using AllocFactor_Core< ::AllocFactorScientific >::getFactor;
Note that the following doesn't work either because of the class name injection:
using AllocFactor_Core< AllocFactorScientific >::getFactor;

AllocFactor_Core<AllocFactorScientific<Mantissa,Exponent,Base,Tag>> should be AllocFactor_Core<AllocFactorScientific>

When typing nested template parameters, be sure to include at least one space between each >
C++ parser gets confused by
AllocFactor_Core<AllocFactorScientific<Mantissa,Exponent,Base,Tag>>
It should be
AllocFactor_Core<AllocFactorScientific<Mantissa,Exponent,Base,Tag> >

Related

Enum class defined in header file does not work in struct which is located in another header file?? C++

SomeHeader.h:
enum class TypeEnum
{
None = 0,
BYTE,
UBYTE,
SHORT,
USHORT
};
AnotherHeader.h
struct Structure
{
TypeEnum type;
};
Throws An Error:
C3646 'type': unknown override specifier
EDIT:
Nobody seems to know the reason so am leaving additional info which might not be related:
TypeEnum has 33 Elements in my real code
It's located on top of the header file
Everything works fine in other headers
Other Structs In AnotherHeader.h With TypeEnum don't work as well
When I define TypeEnum in AnotherHeader.h it says enum class redefinition as it should
Changing to TypeEnum to enum instead of enum class does not work
Other enums don' work as well
Code:
SomeHeader.h:
enum class TypeSpec
{
None = 0,
BYTE,
UBYTE,
SHORT,
USHORT,
INT,
UINT,
FLOAT,
DOUBLE,
VEC2,
VEC3,
VEC4,
VEC2I,
VEC3I,
VEC4I,
VEC2U,
VEC3U,
VEC4U,
VEC2D,
VEC3D,
VEC4D,
MAT2,
MAT3,
MAT4,
MAT2I,
MAT3I,
MAT4I,
MAT2U,
MAT3U,
MAT4U,
MAT2D,
MAT3D,
MAT4D
};
AnotherHeader.h:
struct BufferElement
{
const char* name;
TypeSpec type;
unsigned int size;
unsigned int offset;
bool normalized;
BufferElement() : name("none"), type(TypeSpec::None), size(0), offset(0), normalized(false) {}
BufferElement(TypeSpec _type, const char* _name, bool _normalized = false) :
name(_name), type(_type), size(RenderCommand::getTypeComponentCount(type)), offset(0), normalized(_normalized) {}
};
If you've given us all of AnotherHeader.h, where is the include?
#include "SomeHeader.h"
We do this ALL THE TIME. It's trivial. Define something in one header and #include it at the top of anywhere else you need it. Oh, you should also do this at the top of all .h files:
#pragma once
This keeps the file from being included more than once. (It ignores multiple appearances.)
So your entire SomeHeader would look like:
#pragma once
#include "SomeHeader.h"
struct BufferElement
{
TypeEnum type;
};
Assuming you aren't doing weird stuff with namespaces you haven't actually shown us.

Priority Queue Compilation Error

I'm attempting to compile the code below, but the compiler gives the error
Struct.h:38:9: error: ‘priority_queue’ in namespace ‘std’ does not name a type
Several searches failed to reveal an answer so I'm hoping you guys can help out. The code was partially based on the sample code given at the c++ reference site.
struct aimedShot;
union moveFunc;
struct timeCommand;
struct aimedShot
{
void (*move) (Dot*, SDL_Event&, double x, double y);
double x;
double y;
};
//Holds the kind of function used
union moveFunc
{
void (*notAimed) (Dot*);
aimedShot aimed;
};
//Dot to be operated on and the appropriate operator with time
struct timeCommand
{
Dot* target;
moveFunc command;
int time;
bool type; //True indicates aimed (integer inputs), False indicates unaimed
};
class CompareCommand
{
public:
bool operator()(timeCommand& c1, timeCommand& c2) //Return true if c1 comes first
{
return (c1.time < c2.time);
}
};
typedef std::priority_queue< timeCommand, std::vector<timeCommand>, CompareCommand> commandTimeline;
To be able to use std::priority_queue<> class template you need to #include <queue> standard header.

Can a constexpr class template literal type be parameterized on a non-literal type?

I am playing around with an ORM design using gcc 4.9.2. I have a class of 2 members:
class Staff : public Db::TableBase<Staff> {
public:
long int staffId_;
std::string nickname_;
}
(TableBase is a class I use to pull in several static functions and subclass declarations into class scope. It has no members or methods, only static functions and subclass declarations.)
I have have a ColumnObject for each member:
static constexpr auto colTest1=Db::detail::ColumnObject<Staff,long int>
(&Staff::staffId_,"staff_id",Db::BigSerial | Db::Default,Db::Transport::TEXT);
static constexpr auto colTest2=Db::detail::ColumnObject<Staff, std::basic_string<char> >
(&Staff::nickname_,"nick_name",Db::NotNull,Db::Transport::TEXT);
The first statement compiles, the second does not:
~/git/WebSchedule2/src/common/ORM/Staff.hpp:110:152: error: ‘const Db::detail::ColumnObject<Staff, std::basic_string<char> >{&Staff::nickname_, ((const char*)"nick_name"), 1, (Db::Transport)0, -1}’ is not a constant expression
static constexpr auto colTest2=Db::detail::ColumnObject<Staff, std::basic_string<char> >(&Staff::nickname_,"nick_name",Db::NotNull,Db::Transport::TEXT);
You might say that the reason the second statement doesn't compile is because the type dependency on std::string makes it a non-literal. However, I don't actually use a string in the definition of ColumnObject, I only use the type information.The definition of ColumnObject:
template<typename Derived,typename MemberType>
class ColumnObject {
public:
MemberType Derived::*memberPtr_;
char const *columnName_;
int const traits_;
Db::Transport transport_;
int columnNumber_;
constexpr ColumnObject()
: memberPtr_(nullptr), columnName_("UNITIALIZED COLUMN"), traits_(-1),
transport_(Db::Transport::TEXT), columnNumber_(-1) { }
constexpr ColumnObject(MemberType Derived::*memberPtr, char const *columnName,
int const traits, Db::Transport transport)
: memberPtr_(memberPtr), columnName_(columnName), traits_(traits),
transport_(transport), columnNumber_(-1) { }
}
Any ideas how I can work around this?
(Edit: I am including a complete example below. The problem seems to be using static constexprs.)
// g++ -Wall -Wextra -pedantic -std=c++14 -c foo.cpp
#include <string>
template<typename Derived,typename MemberType>
class ColumnObject;
template<typename Derived,typename MemberType>
class ColumnObject {
public:
MemberType Derived::*memberPtr_;
char const *columnName_;
constexpr ColumnObject()
: memberPtr_(nullptr), columnName_("UNITIALIZED COLUMN") { }
constexpr ColumnObject(MemberType Derived::*memberPtr, const char *columnName)
: memberPtr_(memberPtr), columnName_(columnName) { }
};
class Staff {
public:
long int staffId_;
std::string nickname_;
Staff(){
staffId_=0;
nickname_="";
}
Staff(long int snid, std::string nname)
: staffId_(snid), nickname_(nname)
{
};
static constexpr auto colTest1=ColumnObject<Staff,long int>(&Staff::staffId_,"staff_id");
static constexpr auto colTest2=ColumnObject<Staff, std::string >(&Staff::nickname_,"nick_name");
};
int main(int argc, char *argv[]){
constexpr auto colTest3=ColumnObject<Staff,long int>(&Staff::staffId_,"staff_id");
constexpr auto colTest4=ColumnObject<Staff, std::string >(&Staff::nickname_,"nick_name");
}
working fine here, on clang :) -> coliru.stacked-crooked.com/a/b9a3102e4849b0d0 – pepper_chico
This now works in RedHat gcc 5.3.1-2. – user2352497

c++ static class variable without cpp file

I have a simple class for storing sensor data which can be summarized as
class Data
{
public:
Data(){timestamp = Time::now(); id = sNextID++; data = 0; type = DATA_TYPE_UNKNOWN;}
double data;
Time timestamp;
DataType type;
private:
static unsigned int sNextID;
};
I have a header file that declares a bunch of similar data classes. Given the simplicity of the classes there is no need for an implementation cpp file.
The problem is, without an implementation file how do I initialize sNextID? I read somewhere that it defaults to 0 which would be fine, although relying on that seems a bit hackish. More importantly, though, without initializing it somewhere the linker complains of an undefined reference.
Use inline function (free-standing or member):
inline unsigned &sNextID()
{
static unsigned data = 0;
return data;
}
Or class template (defenition of it's statics can be in header file):
template<typename tag>
struct Foo
{
static unsigned sNextID;
};
template<typename tag>
unsigned Foo<tag>::sNextID=0;
Update: In C++17 inline variables are available:
struct Foo
{
static inline unsigned sNextID;
};
in the header file (let's say it's name is data.h), add this at the end
class Data
{
.....
private:
static unsigned int sNextID;
};
#ifdef MY_INIT
unsigned int sNextID = 0;
#endif
in the file where you have main
#define MY_INIT
#include "data.h"
in all other files where you are including the header, just a plain
#include "data.h"
This will ensure that the line unsigned int sNextID = 0; will be compiled into only one translation unit - the one with main.

c++: Passing const int to template function

I am using the rapidxml lib.
It defines a function to parse files in this way:
template<int Flags>
void parse(Ch *text)
The lib provides const int flags for example:
const int parse_declaration_node = 0x20;
So I created a pointer to a static int in my class:
const int * parser_mode;
And in the class constructor I assigned it its value:
parser_mode = &rapidxml::parse_declaration_node;
Then when I try to use this const int * as template argument to the parse function:
tree->parse<parser_mode>(file->data());
I get this error message:
error: ‘GpxSectionData::parser_mode’ cannot appear in a
constant-expression
This rest of the statement seems correct since:
tree->parse<0>(file->data());
doesn't produce compilation error...
Could you please tell me what I am missing here?
Thank you!
Thanks to the explanations below I will probably define it out of the class:
So I think this is:
class Myclass {
static const int parser_mode;
[...]
}
static const int Myclass::parser_mode = rapidxml::parse_declaration_node;
template<int Flags> void parse(Ch *text) ... const int * parser_mode;
Your template takes an int as a template parameter, but you are passing it an int*. The types int and int* are not the same.
Try tree->parse<rapidxml::parse_declaration_node>(file->data());
You cannot use variable for value of template parameter.
Instead you can add Flags template parameter to your class
template<int Flags>
class CClass {
//...
};
And set Flags parameter for class instance
CClass<rapidxml::parse_declaration_node> obj;