Offsetof alternative for modern C++ - visual-c++

I'm trying to add a map to my datatype that maps member name strings to the local offset of the member variable like this:
struct E
{
B memberX;
B memberY;
constexpr static entry map[] = {
{ "memberX", offsetof( E, memberX ) },
{ "memberY", offsetof( E, memberY) }
};
};
This doesn't compile with VS2015. If fails at { "memberX", offsetof( E, memberX ) }, with error C2227.
Besides, I know that offsetof doesn't work reliably for non pod types.
Do you have a suggestion how to do what I want in a compatible, modern way?
Thanks!

Not that this way is modern, but offsetof is often defined as following:
#define offsetof(type, memb) (intptr_t)&(((type)NULL)->memb)
so you can try using that as alternative.

I am assuming that you want to use the offsets only to access the members later. In that case and given that all members have the same type, a pointer-to-data-member is probably safer and more general:
struct E
{
B memberX;
B memberY;
static const auto& getMemberMap {
static const std::map<std::string, B E::*> memberMap {
{ "memberX", &E::memberX },
{ "memberY", &E::memberY }
};
return memberMap;
};
B& getMember(const std::string& str) {
auto it = getMemberMap().find(str);
if(it == getMemberMap().end()) {
// throw some exception
}
return this->*(it->second);
};
};
std::map does not have a constexpr constructor, so the map will be built runtime rather than compile-time, but you can replace it with your own implementation.
I used a local static variable instead of a static member because you required the initializiation to be contained in the class definition.

Related

Enum class to string

I’m having a solution with switch cases but there are many cases so clang-tidy is giving warning for that function. My motive is to decrease the size of function. Is there any way that we can do to decrease size of function.
As enum class can be used as key for std::map, You can use the map to keep relation of enum <-> string, like this:
enum class test_enum { first, second, third };
const char* to_string(test_enum val) {
static const std::map<test_enum,const char*> dict = {
{ test_enum::first, "first" },
{ test_enum::second, "second" },
{ test_enum::third, "third" }
};
auto tmp = dict.find(val);
return (tmp != dict.end()) ? tmp->second : "<unknown>";
}
C++ has no reflection, so map cannot be filled automatically; however, using compiler-specific extensions (e.g. like __PRETTY_FUNCTION__ extension for GCC) it can be done, e.g. like in magic_enum library

Vala, string to enum

Is there a way to convert a string to an enum in vala:
string foo = "Enum1";
MY_ENUM theEnum = MY_ENUM.get_value_by_name(foo);
enum MY_ENUM {
Enum1,
Enum2,
Enum3
}
So in this example "theEnum" would have the value: MY_ENUM.Enum1
It is possible using the runtime type system provided by GLib's GObject library. There are EnumClass and EnumValue. These provide introspection at runtime and allow an enum to be initialised from a string.
The syntax is a bit complex at present, although it may be possible for someone to modify the Vala compiler to make it easier, but that is a significant piece of work.
An example:
void main () {
try {
MyEnum? the_enum_value;
the_enum_value = MyEnum.parse ("FIRST");
print (#"$(the_enum_value)\n");
} catch (EnumError error) {
print (#"$(error.message)\n");
}
}
errordomain EnumError {
UNKNOWN_VALUE
}
enum MyEnum {
FIRST,
SECOND,
THIRD;
public static MyEnum parse (string value) throws EnumError {
EnumValue? a;
a = ((EnumClass)typeof (MyEnum).class_ref ()).get_value_by_name ("MY_ENUM_" + value);
if (a == null) {
throw new EnumError.UNKNOWN_VALUE (#"String $(value) is not a valid value for $(typeof(MyEnum).name())");
}
return (MyEnum)a.value;
}
}

How to multiply strings in Haxe

I'm trying to multiply some string a by some integer b such that a * b = a + a + a... (b times). I've tried doing it the same way I would in python:
class Test {
static function main() {
var a = "Text";
var b = 4;
trace(a * b); //Assumed Output: TextTextTextText
}
}
But this raises:
Build failure Test.hx:6: characters 14-15 : String should be Int
There doesn't seem to be any information in the Haxe Programming Cookbook or the API Documentation about multiplying strings, so I'm wondering if I've mistyped something or if I should use:
class Test {
static function main() {
var a = "Text";
var b = 4;
var c = "";
for (i in 0...b) {
c = c + a;
}
trace(c); // Outputs "TextTextTextText"
}
}
Not very short, but array comprehension might help in some situations :
class Test {
static function main() {
var a = "Text";
var b = 4;
trace( [for (i in 0...b) a].join("") );
//Output: TextTextTextText
}
}
See on try.haxe.org.
The numeric multiplication operator * requires numeric types, like integer. You have a string. If you want to multiply a string, you have to do it manually by appending a target string within the loop.
The + operator is not the numeric plus in your example, but a way to combine strings.
You can achieve what you want by operator overloading:
abstract MyAbstract(String) {
public inline function new(s:String) {
this = s;
}
#:op(A * B)
public function repeat(rhs:Int):MyAbstract {
var s:StringBuf = new StringBuf();
for (i in 0...rhs)
s.add(this);
return new MyAbstract(s.toString());
}
}
class Main {
static public function main() {
var a = new MyAbstract("foo");
trace(a * 3); // foofoofoo
}
}
To build on tokiop's answer, you could also define a times function, and then use it as a static extension.
using Test.Extensions;
class Test {
static function main() {
trace ("Text".times(4));
}
}
class Extensions {
public static function times (str:String, n:Int) {
return [for (i in 0...n) str].join("");
}
}
try.haxe.org demo here
To build on bsinky answer, you can also define a times function as static extension, but avoid the array:
using Test.Extensions;
class Test {
static function main() {
trace ("Text".times(4));
}
}
class Extensions {
public static function times (str:String, n:Int) {
var v = new StringBuf();
for (i in 0...n) v.add(str);
return v.toString();
}
}
Demo: https://try.haxe.org/#e5937
StringBuf may be optimized for different targets. For example, on JavaScript target it is compiled as if you were just using strings https://api.haxe.org/StringBuf.html
The fastest method (at least on the JavaScript target from https://try.haxe.org/#195A8) seems to be using StringTools._pad.
public static inline function stringProduct ( s : String, n : Int ) {
if ( n < 0 ) {
throw ( 1 );
}
return StringTools.lpad ( "", s, s.length * n );
}
StringTools.lpad and StringTools.rpad can't seem to decide which is more efficient. It looks like rpad might be better for larger strings and lpad might be better for smaller strings, but they switch around a bit with each rerun. haxe.format.JsonPrinter uses lpad for concatenation, but I'm not sure which to recommend.

ambiguous copy constructors vc 2008

I'm trying to recompile older code in latest Visual Studio (2008) and code that worked previously now fails to compile. One of the problems is due to overloaded operators for my class. below there is simplified class to demonstrate the problem. If I remove casting operators for int and char* then it works fine. So one of the ways to fix my issue is to replace them with procedures to_char and to_int and use them instead but it will require a lot of changes in the code (that class is heavily used). There must be some better, smarter way to fix it. any help is greatly appreciated :-)
class test
{
public:
test();
test(char* s2);
test(int num);
test(test &source);
~test();
operator char*();
operator int();
};
test::test() {
}
test::test(char* s2) {
}
test::test(int num) {
}
test::test(test &source) {
}
test::operator char*() {
}
test::operator int() {
}
test test_proc() {
test aa;
return aa;
}
int test_proc2(test aa)
{
return 0;
}
int main()
{
test_proc2(test_proc());
}
//test.cpp(60) : error C2664: 'test_proc2' : cannot convert parameter 1 from 'test' to 'test'
// Cannot copy construct class 'test' due to ambiguous copy constructors or no available copy constructor
Try changing
test(test &source);
to
test(const test &source);
The issue is that the test_proc call returns a temporary test object, which can be passed to a function that accepts a const reference, but not a plain reference.

How to use stdext::hash_map?

I would like to see a simple example of how to override stdext::hash_compare properly, in order to define a new hash function and comparison operator for my own user-defined type. I'm using Visual C++ (2008).
This is how you can do it
class MyClass_Hasher {
const size_t bucket_size = 10; // mean bucket size that the container should try not to exceed
const size_t min_buckets = (1 << 10); // minimum number of buckets, power of 2, >0
MyClass_Hasher() {
// should be default-constructible
}
size_t operator()(const MyClass &key) {
size_t hash_value;
// do fancy stuff here with hash_value
// to create the hash value. There's no specific
// requirement on the value.
return hash_value;
}
bool operator()(const MyClass &left, const MyClass &right) {
// this should implement a total ordering on MyClass, that is
// it should return true if "left" precedes "right" in the ordering
}
};
Then, you can just use
stdext::hash_map my_map<MyClass, MyValue, MyClass_Hasher>
Here you go, example from MSDN
I prefer using a non-member function.
The method expained in the Boost documentation article Extending boost::hash for a custom data type seems to work.

Resources