Default value for template constant in C++ - c++

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.

Related

static_assert inside template or class, gotcha

On this subject, I have read few relevant SO questions/answers/comments. Found only one relevant but somewhat buried question/answer here. Allow me to try and clearly show the issue in question/answer manner. For the benefit of others.
Let the code speak. imagine you design this template.
// value holder V1.0
// T must not be reference or array or both
template<typename T> struct no_arrf_naive
{
static_assert(!std::is_reference_v<T>, "\n\nNo references!\n\n");
static_assert(!std::is_array_v<T>, "\n\nNo arrays!\n\n");
using value_type = T;
T value;
};
Simple and safe, one might think. Some time after, other folks take this complex large API, where this is buried deep, and start using it. The struct above is deep inside. As usually, they just use it, without looking into the code behind.
using arf = int(&)[3];
using naivete = no_arrf_naive<arf>;
// the "test" works
constexpr bool is_ok_type = std::is_class_v< naivete >;
// this declaration will also "work"
void important ( naivete ) ;
But. Instantiations do not work
naivete no_compile;
static assert message does show all of a sudden. But how has the "test" compiled and passed? What is going on here?
The issue is that API is wrong. static_assert as class member does "kick-in" but not before instantiation.
First the offending API commented
template<typename T>
struct no_arrf_naive
{
// member declarations
// used only on implicit instantiation
// https://en.cppreference.com/w/cpp/language/class_template#Implicit_instantiation
static_assert(!std::is_reference_v<T>, "\n\nNo references!\n\n");
static_assert(!std::is_array_v<T>, "\n\nNo arrays!\n\n");
using value_type = T;
T value;
};
Users are here properly coding to transform from Template to Type, but, static_assert's do not kick-in:
using naivete = no_arrf_naive<arf>;
This might most worryingly go on unnoticed, until someone wants to use this. That will not compile and the message, API author has placed in there, will show at last. But alas, too late.
And on projects laboring on some large C++ source, problems that show up late, are the most notorious ones.
The solution is good old SFINAE. The API fixed is this:
// value holder
// references or arrays or both are excluded at compile time
template<typename T,
std::enable_if_t<
(!std::is_reference_v<T> && !std::is_array_v<T>), bool> = true
> struct no_arrf
{
using value_type = T;
T value;
};
The above will not compile immediately upon trying to create the type from template with either reference or array or both:
// reference to array of three int's
using arf = int(&)[3] ;
// no can do
using no_naivete = no_arrf<arf>;
(MSVC) error C2972: 'no_arrf':
template parameter 'unnamed-parameter':
the type of non-type argument is invalid
I might think this whole story might look like trivial or even useless to some. But, I am sure many good folks are coming to SO for badly needed standard C++ advice. For them, this is neither trivial nor useless.
Many thanks for reading.

Warning unused variable using typeid

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();

Mixing pointers to const structs in C++ classes -- declaring a struct on the arguments list?

I'm developing for an embedded hardware using C++ and I often use pointers to const (ROM) structs to minimize the object sizes.
When I get a pointer passed to my class constructor, I want the compiler to create another ROM object based on the one I passed but with one or two arguments changed and just then call the parent class constructor (Display_Element). Any ideas of how this could be done?
Since a const string can be declared within a parameter list I though possibly there could be a way of also declaring a const struct within a parameter list.
I wanted to do something like this, (which is illegal in C++)
Button::Button(const Colors_const* ecc, const Display_element_const* edc, const Element_const* eec, char* elabel,
Display_element* eparent, Screen* escreen) :
Display_element(ecc, cc,Display_element_const {
edc->xi+200,
edc->xf,
edc->yi,
edc->yf,
edc->font_size,
edc->image,
edc->image_x_offset,
edc->image_y_offset,
edc->label_x_offset,
edc->label_y_offset,
edc->mouse_down_ptr,
NULL,
edc->largura_borda_externa,
edc->borda_panel
},
eec,elabel,eparent,escreen) {
flags.largura_borda = 2;
//flags.largura_borda_externa = 3;
flags.borda_light_shadow = true;
flags.sliding_text = true;
flags.dont_paint_on_click = false;
}
Thanks
Well, it seems what I want to do is really illegal and can't be done in C. But philosophically I keep asking myself: if I can allocate a const char[n] written inside a parameter list such as fn(...,"The brow dog",...) why not a way to allocate a const struct the same way? If someone knows the answer, please post!
The workaround I found is to do it the canonical way: declare a const struct and then later assign the appropriate pointer to the struct (something I wanted to be done inside Display_element function on the first place). It solves my problem, but not the conceptual question I've been trying to formulate...
const Display_element_const new_ec = {
edc->xi+200,
edc->xf,
edc->yi,
edc->yf,
edc->font_size,
edc->image,
edc->image_x_offset,
edc->image_y_offset,
edc->label_x_offset,
edc->label_y_offset,
edc->mouse_down_ptr,
NULL,
edc->largura_borda_externa,
edc->borda_panel
};
Button::Button(const Colors_const* ecc, const Display_element_const* new_edc, const Element_const* eec, char* elabel,
Display_element* eparent, Screen* escreen) :
Display_element(ecc, edc,eec,elabel,eparent,escreen) {
//previously dc = edc, assigned inside Display_element fn
dc = &new_ec;

offsetof() of nested C struct in C++

I'm trying to add a socket filter to one of my sockets in C++ (Linux). In the socket filter I need to get the offset of struct fork_proc_event, which is nested within another structure. The definition looks like this (cn_proc.h):
struct proc_event {
...
union {
...
struct fork_proc_event {
__kernel_pid_t parent_pid;
...
} fork;
...
} event_data;
...
};
In C I would do this:
int off = offsetof(struct fork_proc_event, parent_pid);
However I'm developing in C++. If I try to do this:
int off = offsetof(proc_event::fork_proc_event, parent_pid);
I get the following error:
error: expected type-specifier
error: expected `,'
error: expected `)' before ',' token
How should the offsetof() line look like?
It may help to think of how an implementation of an offsetof macro might go. Here's one example:
#define offsetof(TYPE, MEMBER) \
((uintptr_t)&(((TYPE*)0)->MEMBER))
In other words, using 0 as a pointer to the type you're interested in, and simply taking the address of the struct field...
So if you wanted the offset of parent_pid relative to fork (which is how I initially parsed your question):
((char*)&((struct proc_event*)0)->event_data.fork.parent_pid) - ((char*)&((struct proc_event*)0)->event_data.fork)
On second reading it sounds like you might just want the offset of parent_pid relative to the start of struct proc_event. Adapting the example above that would be:
((uintptr_t)&((struct proc_event*)0)->event_data.fork.parent_pid)
I don't exactly understand the need for all those hacks, when all you have to do is give a name to your nested union type. Any name, just to be able to refer to it in C++ code
struct proc_event {
...
union whatever {
...
struct fork_proc_event {
__kernel_pid_t parent_pid;
...
} fork;
...
} event_data;
...
};
Then you'll be able to refer to it as proc_event::whatever::fork_proc_event in offsetof in C++ code
size_t off = offsetof(proc_event::whatever::fork_proc_event, parent_pid);
If you are interested in offset of parent_pid from the beginning of proc_event, you can do
size_t off = offsetof(proc_event, event_data.fork.parent_pid);
If you cannot change the declaration, you can calculate the offset of parent_pid inside fork_proc_event by doing
size_t off =
offsetof(proc_event, event_data.fork.parent_pid) -
offsetof(proc_event, event_data.fork);
(Although I can't say right away whether the last two are formally legal examples of offsetof usage, they will normally work in practice without any problems.)

Would the following code causing problems in C++?

I saw someone writing code like this , in a C++ class:
int foo ( int dummy )
{
this->dummy = dummy;
}
Shall we use code like that , will it cause problems ?
I tried to compile something like this , it seems to be worked.
#update:
I posted this mostly about the name dummy , and the internal variable this->dummy , and if it's problem causing
That's perfectly fine for a member function, other than you're missing a return statement. dummy will shadow the member variable and so you use this-> to refer to member.
int foo ( int dummy )
{
this->dummy = dummy; // set member to argument
return this->dummy;
}
Don't do this for things more complex than a simple set function, as it's confusing.
int foo ( int dummy ) // Bad practise! Rename this param as the function isn't a setter
{
this->dummy = dummy * 2 + 1;
return this->dummy;
}
There is nothing wrong with doing that perse. It can get confusing though if you use dummy assuming it is coming from the class but its actually coming from the parameter.
IMO, its better to use something to denote it is a class member. Some people use simply mDummy, other m_Dummy, others just write dummy_.
Its up to you what you prefer but most of all you should be consistent.
The code is not fine. The function is defined as returning an int but there is no return statement. The compiler might only give a warning about this, but the function calling foo might expect it to return a valid value, which it doesn't, and bad stuff might happen.
You have to do it this way if you're passing a parameter with the same name as the member variable.
But it might be a better practice to avoid a hidden (member-)variable by using different names. There's different coding styles, some would use dummy_, some would use mDummy or other ways to name member variables. This makes your code less confusing.
Well there is nothing wrong with your use, but the code needs to return an int as its an int function :)
Dummy variable in your current class is assigned to the passed int, however do remember they are different but now pointing to the same thing, therefore its better to give it a different name as its in a different.
You could however loose precision under certain variable types.
#include <stddef.h>
typedef struct intlist {
int size;
int i[1];
} intlist;
intlist *
makeintlist (int size)
{
intlist *ilp = malloc (offsetof (intlist, i[size])); /* not C++ */
ilp->size = size;
return ilp;
}
member variable size is allocated to size
That will work.
Don't do it, it's confusing!