Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Instantiate different definition of ctor from template parameter

28 views
Skip to first unread message

wyn...@gmail.com

unread,
Apr 13, 2019, 6:34:48 AM4/13/19
to
How should the idea be implemented to instantiate different definition
of ctors from the template parameter Memcpy_able?

//----- file t1.cpp -----

#include <iostream>
#include <string.h> // for memcpy

template<typename T, bool Memcpy_able>
class Vect {
T m_0, m_1, m_2;

public:

// Memcpy_able is false (how to enable this definition and the next one
// for different value of Memcpy_able?)
//
// Vect(const T(&arr)[3])
// : m_0(arr[0]), m_1(arr[1]), m_2(arr[2]) {};

// Memcpy_able is true
// (Let's assume memcpy can work correctly for the moment)

Vect(const T(&arr)[3]) {
::memcpy(&m_0,arr,sizeof(this));
};
};

int main()
{
char carr[3]={};

Vect<char,true> v(carr);

std::cout << sizeof(v) << std::endl;
return 0;
}
//-------------------------

Another question is, while trying out the solution, I guessed some rule
of c++ (or g++) might have changed because the value sizeof(Vect<char,true>)
was used to 3*4=12, not 3. Can someone explain this?

[me@localhost]$ g++ t1.cpp
[me@localhost]$ ./a.out
3

Bonita Montero

unread,
Apr 13, 2019, 7:14:39 AM4/13/19
to
Classes that have a user-defined constructor aren't pods and
_theoretically_ shouldn't memcpy()'d. But in this case there
arent any complex members so that you won't get into trouble
with any compiler.

Sam

unread,
Apr 13, 2019, 10:47:35 AM4/13/19
to
wyn...@gmail.com writes:

> How should the idea be implemented to instantiate different definition
> of ctors from the template parameter Memcpy_able?
>
> //----- file t1.cpp -----
>
> #include <iostream>
> #include <string.h> // for memcpy
>
> template<typename T, bool Memcpy_able>
> class Vect {
> T m_0, m_1, m_2;
>
> public:
>
> // Memcpy_able is false (how to enable this definition and the next one
> // for different value of Memcpy_able?)
> //
> // Vect(const T(&arr)[3])
> // : m_0(arr[0]), m_1(arr[1]), m_2(arr[2]) {};
>
> // Memcpy_able is true
> // (Let's assume memcpy can work correctly for the moment)
>
> Vect(const T(&arr)[3]) {
> ::memcpy(&m_0,arr,sizeof(this));
> };
> };

What I would do is pull out these class members into a different template,
and simply specialize it, then have this `Vect` inherit from it, something
like:

template<typename T, bool Memcpy_able> class Vect_base;


template<typename T>
class Vect_base<T, false> {

protected:
T m_0, m_1, m_2;

// First constructor
};


template<typename T>
class Vect_base<T, true> {

protected:
T m_0, m_1, m_2;

// First constructor
};

// If the constructor doesn't need anything else to do, simply inherit it:

template<typename T, bool Memcpy_able>
class Vect : Vect_base<T, Memcpy_able> {

public:
using Vect_base::Vect_base;


It's possible that Vect's 2nd template parameter won't be needed at all, and
it can figure out what it must be, for the inherited superclass.

> Another question is, while trying out the solution, I guessed some rule
> of c++ (or g++) might have changed because the value sizeof(Vect<char,true>)
> was used to 3*4=12, not 3. Can someone explain this?
>
> [me@localhost]$ g++ t1.cpp
> [me@localhost]$ ./a.out
> 3

No rule of C++ has changed. Padding required by classes or class members is
always implementation defined, and can change from compiler to compiler, or
compiler version.

You cannot assume that there is, or isn't, padding between class members.

me

unread,
Apr 14, 2019, 9:46:28 AM4/14/19
to
Sam於 2019年4月13日星期六 UTC+8下午10時47分35秒寫道:
The base class idea is good enough for me, thanks

> > Another question is, while trying out the solution, I guessed some rule
> > of c++ (or g++) might have changed because the value sizeof(Vect<char,true>)
> > was used to 3*4=12, not 3. Can someone explain this?
> >
> > [me@localhost]$ g++ t1.cpp
> > [me@localhost]$ ./a.out
> > 3
>
> No rule of C++ has changed. Padding required by classes or class members is
> always implementation defined, and can change from compiler to compiler, or
> compiler version.
>
> You cannot assume that there is, or isn't, padding between class members.

OK, I take the word. It's just g++ implementaion's favor of current release

James Kuyper

unread,
Apr 15, 2019, 8:40:39 AM4/15/19
to
"For any object (other than a base-class subobject) of trivially
copyable type T, whether or not the object holds a valid value of type
T, the underlying bytes (1.7) making up the object can be copied into an
array of char or unsigned char.
If the content of the array of char or unsigned char is copied back into
the object, the object shall subsequently hold its original value." (3.9p2).
It goes on to give memcpy() as an example of how such a copy could be
performed.

Note that this guarantee is tied to "trivially copyable type", not POD type.

Trivially copyable classes are not allowed to have non-trivial copy,
move, copy-assignment or move-assignment, constructors (9p6) - but other
user-defined constructors are permitted.

POD classes includes classes that are merely trivial, but not
necessarily trivially copyable (9p10).
0 new messages