In C++11, I'd like to have a member variable in a class and a constructor for its initialization only if its default template value was chosen (only for supported types like int, of course).
What are recommended ways to achieve this (boost allowed)?
Something like:
template< int _x = -1 > struct C {
C() {} // only available if _x != -1
C( int x ) : x( x ) {} // only available if _x == -1
// more methods that are common for all _x and refer to _x / x
private:
int x; // only available if _x == -1
// more members that are common for all _x
};
Or, put in another way: For size and speed optimization, I would like to use a compile time constant instead of a value stored in a member variable if another value than the template default was chosen.
--
Here is an example to make everything clearer:
template< int _size = -1 > struct Block {
Block() { buf = mmap( _size, ... ); } // exists only when size!=-1
Block( int s ) { buf = mmap( size = s, ... ); } // exists only when size==-1
~Block() { munmap( buf, getSize() ); } // should use the correct size
int getSize() const { return ???; } // gets _size if !=-1, size otherwise
// other methods that use buf and getSize()
private:
void *buf;
const int size; // only exists for size == -1!
};
This solves it partially:
template< int _x > struct X {
int getX() const { return _x; }
};
template<> struct X< -1 > {
X( x ) : x( x ) {}
int getX() const { return _x; }
private:
int x;
};
template< int _x = -1 > struct C : X< _x > {
C() {} // only available if _x != -1
C( int x ) : X< _x >( x ) {} // only available if _x == -1
// more methods that are common for all _x and use this->getX()
};
But what about the constructors of C, and are other / nicer solutions available?
Just an idea, but maybe it helps: You could try to use a base class only for the minimal differences and "fake" the member variable for when it's not there to allow the rest to compile:
template< int _x > class B
{
public:
B() {}
protected:
static const int x = _x;
};
template<> class B< -1 >
{
public:
B( int i ) : x( i ) {}
protected:
int x;
};
template< int _x = -1 >
class C : public B<_x>
{
public:
using B<_x>::B; // inherit B's ctors
void f()
{
if ( x == ... ) // uses either the member variable x or the static const int x!
}
};
but as I said, it's just an idea...
Specialization is the way to go:
template <int N> struct C
{
C(int n) : n_(n) { }
int n;
};
template <> struct C<-1>
{
C() { }
C(int n) : n_(n) { }
int n;
};
I'm with Kerrek SB on this one. Put your common code, namely the runtime buffer handling in a common base class an create two derived classes, one for your statically sized buffer class and one for your dynamic buffer class. Or better yet, according to common coding guidelines, use composition.
class buffer_impl {
public:
buffer_impl(int size) : data_ {mmap( size, ... )}, size_ {size} {}
~buffer_impl() { munmap( data_, getSize() ); }
int getSize() const noexcept { return size_; }
// other buffer routines
// ...
private:
void* data_;
int size_;
};
template <int _size = -1 >
class buffer { // static size
public:
buffer() : impl_ {_size} {}
static constexpr int getSize() noexcept { return _size; }
private:
buffer_impl impl_;
};
template <>
class buffer<-1> { // dynamic size
public:
buffer(int size) : impl_ {size} {}
int getSize() const noexcept { return impl_.getSize(); }
private:
buffer_impl impl_;
};
Related
I am trying to implement a general value class in C++ that can contain integer, float, and fractions, etc. So I wrote an interface value_interface and had int wrapped up in int_wrapper to inherit from the interface.
However, value(3) will not initialize a value object, because even if 3 is convertable to int_wrapper, which is convertable to value_interface, value_interface is not directly convertable to value. Is there a way to make value(3) possible? Or is there a better way to do this?
#include <string>
class value_interface {
public:
virtual std::string to_string() const = 0;
virtual ~value_interface() {}
};
class value {
std::shared_ptr<value_interface> d_ptr_;
public:
value(value_interface* x) { d_ptr_ = std::unique_ptr<value_interface>(x); }
std::string to_string() const { return d_ptr_->to_string(); }
};
class int_wrapper : public value_interface {
int val_;
public:
int_wrapper(const int val) : val_(val) {}
operator int() const { return val_; }
std::string to_string() const override { return std::to_string(val_); }
friend value operator+(int_wrapper x, int_wrapper y);
};
int main() {
value a = 3; // Error C2440 'initializing': cannot convert from 'int' to 'value'
int_wrapper b = 3; // ok
value_interface& c = static_cast<value_interface&>(b); // ok
value d = &c; // ok
return 0;
}
Create a make_value templated function with specialisations for each class. e.g:
template < typename T >
value make_value( const T& t );
template <>
value make_value< int >( const int& i )
{
return value{ std::make_shared< int_wrapper >( i ) };
}
Alternatively you can template the value constructor which will allow you to do value v = 3 directly:
class value {
std::shared_ptr<value_interface> d_ptr_;
public:
value(value_interface* x) { d_ptr_ = std::unique_ptr<value_interface>(x); }
template < typename T >
value( const T& t );
std::string to_string() const { return d_ptr_->to_string(); }
};
template <>
value::value< int >( const int& i )
:d_ptr_(std::make_shared<int_wrapper>(i))
{
}
i'm making a simple map with defined size as parameter, i would like it to be stored in my private member variable.
I will show a simple exemple :
class A {
public:
A (const int size) {
map_size_ = size;
//or | both will not compile
int map[size][size];
}
private:
int map_size_;
int map_[map_size_][map_size_];
}
I know the map_ won't compile, but i wonder how to declare it properly with a const int from the constructor parameter and without pointers.
You should use std::vector
#include <vector>
class A {
public:
explicit A (const int size) {
map_.resize(size);
for (auto &v : map_) v.resize(size);
}
private:
std::vector<std::vector<int>> map_;
};
This might not be the most optimal way from performance point of view, but it is the simplest one. There is no way around that. int[][] declarations do not work with non-compile time values in C++.
Tips:
Use explicit with single argument constructors.
You should use std::size_t instead of int for sizes.
This should work:
class A {
public:
A(int const size) {
_map_size = size;
_map = new int[_map_size * _map_size];
}
private:
int _map_size;
int* _map;
};
UPDATE - apparently people want a more comprehensive solution than the OP asked about.
class A {
public:
A(int const size)
: _map_size(size)
, _map(new int[_map_size * _map_size]) {
}
A(A const&) = delete;
~A() {
delete[] _map;
}
A& operator=(A const&) = delete;
int at(int x, int y) const {
if (x < 0 || x >= _map_size || y < 0 || y >= _map_size)
throw "That coordinate is in the giggleweeds";
return _map[y * _map_size + x];
}
int set_at(int x, int y, int value) {
if (x < 0 || x >= _map_size || y < 0 || y >= _map_size)
throw "That coordinate is in the giggleweeds";
_map[y * _map_size + x] = value;
}
private:
int _map_size;
int* _map;
};
Is the following code valid C++? Otherwise, is there a valid way to simultaneously interpret memory as values of different type?
#include <cstdio>
struct Base { int payload; };
struct D1 : Base { void operator()(){ printf("D1: %d\n", payload);} };
struct D2 : Base { void operator()(){ printf("D2: %d\n", payload);} };
int main()
{
D1 d1;
D2& d2 = static_cast<D2&>(static_cast<Base&>(d1));
d1();
d2();
d2.payload = 3;
d1();
d2();
}
In response to #NickoPo: My use case is basically what follows. Imagine that IntBase is not necessarily cheap to copy, that there are many complex algorithms, some of which profit from numbers being prime vs. odd, and others don't:
#include <cassert>
#include <cstdio>
bool is_odd(int value) { return 0 != value % 2; }
bool is_small_prime(int value) { return 2 == value || 3 == value || 5 == value || 7 == value; }
class IntBase
{
public:
explicit IntBase(int value) : m_value(value) {}
int value() const { return m_value; }
protected:
int m_value;
};
class OddInt : public IntBase
{
public:
explicit OddInt(int value) : IntBase(value) { assert(is_odd(m_value)); }
};
class SmallPrimeInt : public IntBase
{
public:
explicit SmallPrimeInt(int value) : IntBase(value) { assert(is_small_prime(m_value)); }
};
bool is_constrainable_to_odd_int(IntBase const& x)
{
return is_odd(x.value());
}
OddInt const& constrain_to_odd_int(IntBase const& x)
{
assert(is_odd(x.value()));
return static_cast<OddInt const&>(x);
}
bool is_constrainable_to_small_prime_int(IntBase const& x)
{
return is_small_prime(x.value());
}
SmallPrimeInt const& constrain_to_small_prime_int(IntBase const& x)
{
assert(is_small_prime(x.value()));
return static_cast<SmallPrimeInt const&>(x);
}
void algorithm(IntBase const&)
{
printf("algoritm(IntBase const&)\n");
}
void algorithm(OddInt const&)
{
printf("algoritm(OddInt const&)\n");
}
void algorithm(SmallPrimeInt const&)
{
printf("algoritm(SmallPrimeInt const&)\n");
}
void test(IntBase const& x)
{
if (is_constrainable_to_small_prime_int(x))
{
algorithm(constrain_to_small_prime_int(x));
}
else if (is_constrainable_to_odd_int(x))
{
algorithm(constrain_to_odd_int(x));
}
else
{
algorithm(x);
}
}
void test(OddInt const& x)
{
if (is_constrainable_to_small_prime_int(x))
{
algorithm(constrain_to_small_prime_int(x));
}
else
{
algorithm(constrain_to_odd_int(x));
}
}
int main()
{
IntBase x(0);
OddInt y(1);
OddInt z(7);
test(x); // algoritm(IntBase const&)
test(y); // algoritm(OddInt const&)
test(z); // algoritm(SmallPrimeInt const&)
}
Related:
Can I legally reinterpret_cast between layout-compatible standard-layout types?
Answer to Safety of casting between pointers of two identical classes?
If you're going to cast while using similar interfaces while using type as a guarantee, I'd recommend that you just wrap the inner data with your new object type and then provide access to the inner data in order to transfer it from one type to another. There's no point in doing static casting or reinterpret casting if you're not going to do it safely.
Here's an example:
http://coliru.stacked-crooked.com/a/40d5efeff22fcdcd
#include <iostream>
//Base data structure to encapsulate only data.
struct data {
data(int i) : i(i) {}
int i;
};
//Wrapper around our data structure, with interfaces to access
//the values and the data; implement your own constructor to
//gate the value
class PrimeInt {
public:
PrimeInt(const int i)
: d(i) {}
PrimeInt(const data& other)
: d(other) {}
PrimeInt(data&& other)
: d(std::move(other)) {}
PrimeInt& operator=(const PrimeInt&) = default;
PrimeInt& operator=(PrimeInt&&) = default;
int get() {return d.i;};
operator data() {return d;};
private:
data d;
};
//Wrapper around our data structure, with interfaces to access
//the values and the data; implement your own constructor to
//gate the value
class OddInt {
public:
OddInt(const int i)
: d(i) {}
OddInt(const data& other)
: d(other) {}
OddInt(data&& other)
: d(std::move(other)) {}
OddInt& operator=(const OddInt&) = default;
OddInt& operator=(OddInt&&) = default;
int get() {return d.i;};
operator data() {return d;};
private:
data d;
};
//Notice that we can now implicitly cast from one type to another.
int main() {
PrimeInt pi(10);
std::cout << pi.get() << std::endl;
OddInt oi(pi);
std::cout << oi.get() << std::endl;
return 0;
}
If your objects are not cheap to copy, you are probably passing pointers or references everywhere. You can wrap pointers to your common base in different class types and pass them by value. That is, instead of this (pseudocode)
class B
class D1 : B { ... }
class D2 : B { ... }
D1* d1; D2* d2;
you have
class Bimpl
class B { Bimpl* bimpl; }
class D1 : B { ... }
class D2 : B { ... }
D1 d1; D2 d2;
Here you never do any built-in cast. If you want to convert D1 to D2, you write your own conversion function.
Consider the following class:
class A {
const int arr[2];
public:
A() { }
};
Is it possible to initialize arr from the constructor initializer list or in any other way than on the line where it is declared (i.e. const int arr[2] = {1,2};)?
Note that I'm interested in methods that work with C++98!
By wrapping them in a struct, e.g.:
class A
{
struct Data
{
int arr[2];
};
Data const arr;
public:
A() : arr( someOtherStruct ) {}
};
This does mean that to access the data, you'd have to write arr.arr.
It's possible to avoid that by inheriting from the struct:
struct PrivateDataForA
{
int arr[2];
};
class A : private PrivateDataForA
{
public:
A() : PrivateDataForA( someOtherStruct ) {}
};
This does make the name of the struct visible outside of the class
(which might be an advantage—client code could pass you one as an
argument).
If you don't have an instance of the struct handy, say because you want
to fill it with values calculated from arguments to the constructor, you
can use a static member function:
class A : private PrivateDataForA
{
static PrivateDataForA createInitializer( int a, int b );
public:
A( int a, int b ) : PrivateDataForA( createInitializer( a, b ) )
{
}
};
For the OP’s concrete example:
#include <iostream>
#include <stddef.h>
typedef ptrdiff_t Size;
typedef Size Index;
template< class Element, Size n >
struct Array{ Element elem[n]; };
class A {
Array<int, 2> const arr_; // const int arr[2];
A& operator=( A const& ); // No such.
static Array<int, 2> const& oneAndTwo()
{
static Array<int, 2> const a = {1, 2};
return a;
}
public:
A(): arr_( oneAndTwo() ) {}
int at( Index i ) const { return arr_.elem[i]; }
};
int main()
{
using namespace std;
A o;
for( int i = 0; i < 2; ++i )
{
cout << o.at( i ) << endl;
}
}
Initializing array elements to non-zero values requires C++11 support.
In C++03, it's only possible to value-initialize your array, resulting in each element's value being 0:
class A {
const int arr[2];
public:
A() : arr() { }
};
For the relevant C++03 standardese, see this question and answer:
How can i use member initialization list to initialize it?
(I'm going to assume that by C++98 you mean not C++11, i.e. that C++03 is acceptable. If this assumption is wrong, please say so.)
No. It's not.
I want to add a operator override to perform assignments/__set__s inline.
Template :-
class CBase {
public :
static void SetupVmeInterface(CVmeInterface *in);
protected :
static CVmeInterface *pVmeInterface;
};
template <class T> class TCVmeAccess : public CBase {
public:
TCVmeAccess(int address);
T get()
{
unsigned long temp = pVmeInterface->ReadAddress(Address);
T ret = *reinterpret_cast<T*>(&temp);
return ret;
};
T *operator->();
unsigned long asLong();
bool set(T data)
{
unsigned long write_data = *reinterpret_cast<unsigned long*>(&data);
return pVmeInterface->WriteAddress(Address, write_data);
};
// void operator->(T);
void operator=(T data)
{ set(data); }
private :
int Address;
};
A struct that will be used in the template :-
typedef struct
{
int a: 1; // 0
int b: 1; // 1
int c: 1; // 2
int d: 1; // 3
int NotUsed : 28; // 31-4
} _HVPSUControl;
Code body :-
TCVmeAccess<_HVPSUControl> HVPSUControl(constHVPSUControlBlock);
_HVPSUControl hvpsu = HVPSUControl.get(); // Yep, good, but not as nice as...
int a = HVPSUControl2.get().OperationalRequestPort; // yep, also good, but...
int b = HVPSUControl->a; // works, and is all go so far
HVPSUControl.set(hvpsu); // works, but need _HVPSUControl type
HVPSUControl = hvpsu; // also works, as operator = is used, but still need type
// this line does not work!
// as the = assignment is redirected into a copy of the struct, not the template
HVPSUControl->a = 1; // this line
So, is there a way to get this line above to work?
Edit:
As in, I want "this line" to perform as a "set" as does in the template class.
Edit:
1. Assign a value directly in-line to a member of the struct that the template is formed
of.
2. Cause that assignment to go though a template accessor.
So that I dont have to do this on assignments :-
// HVPSUControl is predefined and used many times.
_HVPSUControl hvpsu;
hvpsu.a = 1;
HVPSUControl.set(hvpsu);
I want to do
HVPSUControl.a = 1; // or
HVPSUControl->a = 1; // or ?
As gets work on line :
if (HVPSUControl->a)
Instead of overwriting the "->" and the "=" operator, you could derive from the template struct.
template <class T> class TCVmeAccess : public CBase, public T {
public:
TCVmeAccess(int address);
T get();
// T *operator->();
unsigned long asLong();
bool set(T);
// void operator->(T);
// void operator=(T);
private :
int Address;
};
HVPSUControl.a = 1; // and use this for setting a bitfield.
Edit: If you want to use an custom assignment operator, you should declare it in HVPSUControl, or a even a base class of it, if you have more of this control-like structures.
struct _HVPSUControl
{
int a: 1; // 0
int b: 1; // 1
int c: 1; // 2
int d: 1; // 3
int NotUsed : 28; // 31-4
void operator = (int x);
};
or
struct _HVPSUBase {
void operator = (int x);
}
struct _HVPSUControl: public _HVPSUBase
{
int a: 1; // 0
int b: 1; // 1
int c: 1; // 2
int d: 1; // 3
int NotUsed : 28; // 31-4
};
You can't get this line to work any other way. You call TCVmeAccess::operator-> which returns a _HVPSUControl* and then you access _HVPSUControl*::a.
Or do you want to assign integer 1 to the complete _HVPSUControl struct?
template <class T> class TCVmeAccess : public CBase {
public:
// ...
void operator=(T data) { set(data); }
void operator=(int n) { operator=(T(n)); }
// ...
};
typedef struct
{
_HVPSUControl(int n) {
*this = reinterpret_cast<_HVPSUControl>(n);
}
int a: 1; // 0
int b: 1; // 1
int c: 1; // 2
int d: 1; // 3
int NotUsed : 28; // 31-4
} _HVPSUControl;
and then do
HVPSUControl = 1;