I have written a small wrapper for typeinfo to get the typecode of a variable at compile time more easily:
template<typename DataType>
class TypeInfo
{
public:
static const char* typecode()
{
DataType TypedVariable = 0;
const char* code = typeid(TypedVariable).name();
return(code);
};
};
I use it like this:
const char* code = TypeInfo<float>::typecode();
It compiles perfectly fine and works as expected, but I am getting the warning
src/common.hh(153): warning: variable "TypedVariable" was set but never used
detected during:
instantiation of "char TypeInfo<DataType>::typecode() [with DataType=r32]"
...
I am wondering why "calling" typeid() on a variable does not count as using it. I know that it is a defined keyword, but still I am irritated that getting the type of a variable does not count as using it.
The compilation is done using nvcc of CUDA 9.2. Maybe it is a CUDA specific thing?
Thanks for any help :)
//edit:
I made a mistake by not returning the full char* because I use only normal types! Thanks for making me aware of the typo! I also added the template definition. I forgot to copy that over!
Because you don't use the value of TypedVariable. You just use its type (and you can get it's type by rewriting your initialization as:
char const * const code = typeid(DataType).name();
Related
I'm trying to replace a global buffer size to one that can be modifiable for tests. The current code is something like:
static const uint32_t BUFFER_SIZE = 1 << 8;
class BufferWrapper {
.
.
.
char buffer_[BUFFER_SIZE];
};
This causes a problem when I'm trying to change the BUFFER_SIZE for tests. Thus, I was hoping to make the BUFFER_SIZE a template constant, and having a default value for said constant so that I only need to specify it during tests, something like:
static const uint32_t BUFFER_SIZE = 1 << 8;
template <uint_32 SIZE = BUFFER_SIZE>
class BufferWrapper {
.
.
.
char buffer_[SIZE];
};
That way, previous declarations can still compile like:
BufferWrapper buf
But during a test, I could write something like this to test a buffer of 1KB:
BufferWrapper<1024> test_buf;
My question is, is it possible to provide a default for a template value, and how would I do it? The error I get with the above when I declare something like BufferWrapper buf; is:
error: use of class template 'BufferWrapper' requires template arguments; argument deduction not allowed in function prototype
There is no problem with the shown program in C++17.
Prior to C++17, you must provide the template argument list even if it is empty:
BufferWrapper<> test_buf;
In such case you can avoid changing the client code by using a type alias:
template <uint_32 SIZE = BUFFER_SIZE>
class BufferWrapperTemplate;
using BufferWrapper = BufferWrapperTemplate<>;
As this answer states, the code is fine since C++17. However, if you do not have access to that, you can still get around the need to change all existing code to use BufferWrapper<> instead of BufferWrapper.
Do this by renaming BufferWrapper to something else (e.g. BufferWrapperTemplate) and providing a type alias to the default-sized version:
template <uint_32 SIZE = BUFFER_SIZE>
class BufferWrapperTemplate {
.
.
.
char buffer_[SIZE];
};
typedef BufferWrapperTemplate<> BufferWrapper;
This way, all existing code can keep using BufferWrapper, and tests can use BufferWrapperTemplate<42> where needed.
This code:
struct TToken
{
UnicodeString &DBIDs;
std::vector<TToken> T;
TToken(UnicodeString &DI) : DBIDs(DI) {}
void Append(void) {T.push_back(TToken(DBIDs));}
};
UnicodeString DI="25,40,55";
TToken T(DI);
if (T.DBIDs==DI) // if I comment out this comparison it works fine
....
generates the above compiler error (I'm using C++Builder 10.1 Berlin).
If I change the UnicodeString reference to a pointer, it all works as expected. Does anyone know why the reference generates the error?
By the way, is there an easier way of making DBIDs available to every created vector element instead of passing a pointer/reference all the way down the line? A static member is no good, and I did look at template expressions, but couldn't get an acceptable answer.
I want to set default class type as default comparison type in Template and then I want to compares two character strings using templates, I did write code but it’s giving error. Code and error is given below,
class CaseSenCmp{
public:
static int isEqual(char x, char y){ return x==y; }
};
template<typename c=CaseSenCmp>
int compare(char* str1, char* str2){
for(int i=0; i<strlen(str1) && i<strlen(str2); i++)
if(!c::isEqual(str1[i], str2[i]))
return str1[i]-str2[i];
return strlen(str1)-strlen(str2);
}
main(){
char *x = "hello", *y = "HELLO";
compare(x,y);
}
But when i have added this prototype of template, it works
template<typename c>
Compiler gives this error
error: default template arguments may not be used in function templates without -std=c++11 or -std=gnu++11|
Also when i try to do type casting in main function using this code, it also works
compare<CaseSenCmp>(x,y);
But i want to set Default Policy
I also faced this issue in code::blocks. To tackle this issue you have to enable
-std=c++11
into the you compiler. In case of code::blocks you have to follow given below instructions.
Settings->Compiler->Compiler Flags...Look for and check the option to "Have g++ follow the C++11 ISO C++ language standard". If that doesn't get it then also check the box above it for the C++0x standard.
Add -std=c++11 to compilation flags, because another way it won't compile.
Folks,
Problem Statement - Does C++ allow a (static) const be limited to a class scope, so I can get rid of #defines that pollute entire namespace?
My observation is NO (in the following DIFFERENT examples), and I'd like to find out why and what's the best alternative. VS generates error C2589: 'const' : illegal token on right side of '::'
EXAMPLE1
// a.h
class A
{
…
..
static const uint_32 myConst = 1234;
};
//b.cpp
include “a.h”
…
B()
{
uint32_t arr[A::myConst]; // C2589! const : illegal token on right side of '::'
}
EXAMPLE 2
// a.h
class A
{
…
..
enum blah
{
...
myConst = 1234,
..
};
};
//b.cpp
include “a.h”
...
B()
{
uint32_t arr[A::myConst]; // C2589! const : illegal token on right side of '::'
}
When you take your macro:
#define CONST 1234
and substitute it for where you use it:
static const int CONST = 1234;
The end result is nonsense:
static const int 1234 = 1234;
In another instance:
Int a1[a::CONST];
This also becomes nonsense:
Int a1[a::1234];
This all begs the question, what are you trying to do?
It looks like you're trying to create a member variable with the same name as your macro, CONST, here:
class A
{
static const int CONST = 1234;
};
However since when this code is compiled the macro has already been defined, the preprocessor changes this by substituting the macro before the compiler itself can get a crack at it. By the time the code is compiled, it looks like this:
class A
{
static const int 1234 = 1234;
};
Best is to just do away with the macro entirely, and then retrofit your code to use proper constants like you're trying to do here. Don't mix and match. At the very least, don't use the same name for the member as you do for the macro.
First of all your class is called A, as in capital A, not a. The class name is used to qualify the constant you are trying to use. So, change your code to use A::CONST. By the way, this is C++ not C# or Java, so there is no such thing as an Int, unless for some bizarre reason you decided to invent your own integer type.
As an aside, using all caps to name constants can collide with macros and is a good way to get into trouble, especially since pre-processing happens first and macros are substituted for all cases of the constants. This can often lead to invalid C++ code with syntax errors that are difficult to understand. That's why you should never use all caps to name constants, since this is a convention most commonly used for macros.
If I may make a guess, it looks like you're trying to use :: the same way you use . in Python.
It looks like you really don't understand what the scope resolution operator does, or how it works.
:: has a very specific, and quite limited usage. Until you understand it better, we're going to have a really hard time helping you.
I am creating an component, generalization of a template. For creation must be used string identifier.
I am replacing:
#define MYCOMPONENT_CONSTANT_IDENTIFIER "ID value"
with
namespace myComponent
{
static const QString constant_identifier = "ID value"
}
to follow some codding standards (MISRA,...).
This should work regarding C++. And I checked it up at Constants-only header file C++.
This constant is defined in a header of a component "myComponent" and included in a header where my Indexer is initialized and component is created. This has not been changed at replacement time.
Replacement builds successfully, but fails on attempt to run.
Segmentation fault hapends at:
template<>
inline void TMyIndexer::Init()
{
Map(...)
//before
//Map( ENUM_VAL, QSharedPointer<ITableFieldDefs>(new myComponent::TTableFieldDefs(MYCOMPONENT_CONSTANT_IDENTIFIER)) );
Map( ENUM_VAL, QSharedPointer<ITableFieldDefs>(new myComponent::TTableFieldDefs(myComponent::constant_identifier)) );
Map(...)
}
Where:
// TStaticFieldDefs<> implements ITableFieldDefs
typedef TStaticFieldDefs<myComponent::Fields> TTableFieldDefs;
//constructor
TStaticFieldDefs(QString id) : fId(id) {}
If I go up the the stack:
2.) qstring.h: inline QString::QString(const QString &other) : d(other.d)
{ Q_ASSERT(&other != this); d->ref.ref(); }
1.) qatomic_x86_64.h: inline bool QBasicAtomicInt::ref()
I suppose there something wrong in template generalization, inline definition in the constructor or something else I am not aware.
Any explanation is welcome.
I am out of ideas and am kindly asking for help.
My guess is that you're trying to use your constant object from a static context. A C++ standard states that order of static objects initialization is undefined. So you may reference uninitialized object that may cause a segfault.