• Advertisement

• ### Popular Now

• 15
• 15
• 11
• 9
• 10
• Advertisement
• ### Similar Content

• Trying to get ideas here on how I could do this:
I have created a game for a university coursework assignment using a custom game engine (internal to my university, but it's based on OpenGL).
The game loads levels and menus from a file, this happens at initialization to increase performance while playing the game. At the moment the game loading time is 4.1s, but the loading time without the levels and menus is 0.961s- that's over 3s. As more levels are added the loading time will become longer and I want to add a loading screen.
I've tried to add one, but loading the levels and menus is blocking everything else, including rendering the loading screen. This means that the loading screen doesn't appear until the game has loaded and is overridden by the main menu. The game loading is done via its update function and via calling initialization functions of the various game classes, and the loading screen is rendered within the game's render function (the rendering is done on a separate thread, according to the game engine's documentation).
Any suggestions on how I can show the loading screen without the other loading activity blocking it from being shown?
I know that I can use threading but am unsure how thread-safe the operation would be to init the game on another thread.

• I have a particle system with the following layout:
system / emitter / particle

particle is driven by particle data, which contains a range of over lifetime properties, where some can be random between two values or even two curves. to maintain a smooth evaluation between two ranges, i randomize a "lerp offset" on particle init and use that value when evaluating curves. the issue is that i'm using that same offset value for all properties (10ish) and as a result i'm seeing some patterns, which i'd like to remove. The obvious way is to just add more storage for floats, but i'd like to avoid that. The other way is to generate a seed of some sort and a random table, and use that to generate 10 values, ie: start with short/integer, mask it, then renormalize to float 0-1.

any other ideas?
• By dgi
Hey all ,
For a few days I'm trying to solve some problems with my engine's memory management.Basically what is have is a custom heap with pre allocated memory.Every block has a header and so on.I decided to leave it like that(not cache friendly) because my model is that every block will be large and I will have a pool allocators and stack allocators dealing with those blocks internally. So far so good I figure out how to place my per scene resources . There is one thing that I really don't know how to do and thats dealing with containers.What kind of allocation strategy to use here.
If I use vector for my scene objects(entities , cameras , particle emitters .. ) I will fragment my custom heap if I do it in a standard way , adding and removing objects will cause a lot of reallocations . If I use a linked list this will not fragment the memory but it's not cache friendly.I guess if a reserve large amount of memory for those vectors it will work but then I will waste a lot memory.I was thinking for some sort of mix between a vector and a linked list , where you have block of memory that can contain lets say 40 items and if you go over that number a new one will be created and re location of the data would not be needed.There would be some cache misses but it will reduce the fragmentation.

How you guys deal with that ? Do you just reserve a lot data ?

dgi
• By Hermetix
I am trying to setup the custom wizard for making a 3ds MAX 2018 plug-in (to export a character animation data), but I can't locate the wizard file folder to put the .vsz file in. In the 3ds MAX 2018 docs, it only mentions where the folder is in VS 2015 (VC/vcprojects). It's a VC++ project, but I don't see any folder in VC for the wizard files. I'm using VS 2017 update 15.5.6 Enterprise, and the folders in VC are: Auxiliary, Redist and Tools.

Thanks.
• By KarimIO
Hey guys! Three questions about uniform buffers:
1) Is there a benefit to Vulkan and DirectX's Shader State for the Constant/Uniform Buffer? In these APIs, and NOT in OpenGL, you must set which shader is going to take each buffer. Why is this? For allowing more slots?
2) I'm building an wrapper over these graphics APIs, and was wondering how to handle passing parameters. In addition, I used my own json format to describe material formats and shader formats. In this, I can describe which shaders get what uniform buffers. I was thinking of moving to support ShaderLab (Unity's shader format) instead, as this would allow people to jump over easily enough and ease up the learning curve. But ShaderLab does not support multiple Uniform Buffers at all, as I can tell, let alone what parameters go where.
So to fix this, I was just going to send all Uniform Buffers to all shaders. Is this that big of a problem?
3) Do you have any references on how to organize material uniform buffers? I may be optimizing too early, but I've seen people say what a toll this can take.
• Advertisement
• Advertisement

# C++ Char pointer/array type ambiguity

## Recommended Posts

So I'm trying to design a function that acts differently, based on whether it is passed a const char/wchar_t array, or a const char/wchar_t*:

template<typename Char, size_t Length>
size_t stringLength(const Char(&pString)[Length])
{
return Length - 1;
}

template<typename Char>
size_t stringLength(const Char* pType)
{
return strlen(pType);
}

const char* pTest = "Test";
stringLength(pTest); // => should return 4
stringLength("Test"); // => should return 4 as well

The problem is that the last line doesn't compile, saying that the function-call is ambigous between both overloads, even though it correctly identifies the argument as "const char [8]", which works as intended if I remove the "const Char* pType" overload.

Now, why is this ambigous? As far as I understand it, the upper function should be a closer match to the argument list and thus be selected. Is there anything I have to/can do to make that work? (I'm on MSVC 2017)

#### Share this post

##### Share on other sites
Advertisement

Correct me if I'm wrong, but it's ambiguous because char* and char[] are the same type.  Both of them are just pointers to the first character in an array of characters.

#### Share this post

##### Share on other sites
5 minutes ago, trjh2k2 said:

Correct me if I'm wrong, but it's ambiguous because char* and char[] are the same type.  Both of them are just pointers to the first character in an array of characters.

Well, from what I understand, a size-qualified "char[X]"-array isn't exactly the same type as a char*.

For example, you can convert the char[X] to a char*, but not the other way around:

char array[4] = {};
char* pointer;

pointer = array; // works
array = pointer; // doesn't

Also the first function can't be called with char*, and will have the correct array-size if called with a char[X]. So all of this ad least made me belive that they are different types; though obviously the compiler assumes they are ambigous, maybe for the reason you wrote.

I might have another idea that I'm going to try out though, just remembered that there was a std-trait to find out if a type is an array & to get the arrays extent... though thats going to result in more messy template code, so if someone found an easier solution I'd still appreciate it

#### Share this post

##### Share on other sites

The problem I think is not that you can't pass char[x] to a char*, but that you CAN pass "text" to both.

What are you trying to accomplish?  This doesn't look like a good way to check the length of a string.

#### Share this post

##### Share on other sites
24 minutes ago, trjh2k2 said:

The problem I think is not that you can't pass char[x] to a char*, but that you CAN pass "text" to both.

Yes, this is true, yet from how I can see it this only happens via cast (char[x] => char*), so under normal overload resolution rules, I still don't see how it would be any different to:

void func(int x)
{
}

void func(float x)
{
}

func(0); // calls "func(int x)"

I mean you're obviously right about what happens, it just feels wrong to me :>

24 minutes ago, trjh2k2 said:

What are you trying to accomplish?  This doesn't look like a good way to check the length of a string.

Its actually being used as an optimization string-length generation as part of my custom StringView-class:

template<size_t Length>
constexpr BaseStringView(StaticString<Length> pString) : // const Type(&)[Length]
BaseStringView(pString, StringLength<Length>(pString))
{
};

template<size_t Length>
constexpr BaseStringView(DynamicString<Length> pString) : // Type(&)[Length] => prevents issues with user-handled char-buffers
BaseStringView(pString, StringLength(pString))
{
};

I know its technically not 100% safe, but I made sure that it doesn't break anything for me; and since I'm using a string-view I'm already in not-safe territory. As you can see I've got a second overload that gets called when I'm passing in an actual "char array[X];" that is filled from ie. an windows-API method. The actual reason why I'd need the "const char*" overload is that right now this would instead call the "const std::string&" overload, thus creating an unncessary copy & a dangling pointer (if the view is actually locally stored).
Not that it happens that often, most of my codebase has now been ported to use StringView & size-qualified strings, but there's always some places where this could still happen.

#### Share this post

##### Share on other sites

As you said before, char[] and char* are just the same, but depending on what you want to do/need you have to cast. And yeah, you can cast from char[] to char* this way:

char array[4] = {'a','b','c','d'};
char* charPointer = nullptr;

charPointer = &array[0];

You have to point your pointer to the beginning of your char array, there is no direct assignment. You might overload operators if you really use that much char-pointer assignment.

Edited by NajeNDa

#### Share this post

##### Share on other sites

Various fun hacks for this exist at StackOverflow.

#### Share this post

##### Share on other sites

The reference trick in the StackOverflow site is the one I've seen several times over the years:

template<typename T> void f(T* const& c){ std::cout << "pointer\n"; }
template<typename T, size_t N> void f(T(&)[N]){ std::cout << "array\n"; }

Even though you as a programmer don't know, your compiler hitting the code can potentially know.  It works if the parameter being directly passed in is known to be a fixed-length array. If it goes through a single indirection to a pointer and the indirection isn't optimized a way, then the information is lost and the compiler will deduce it as a pointer. If it goes through an indirection and the indirection gets optimized away it can still deduce it correctly.

So even though that can work in some cases, it won't work in all cases after indirections.

The useful cases are almost non-existent.

As for the original problem here on the thread where you're trying to avoid taking the string length, that's not much of a benefit.  You're trying to simplify the interface, but instead you are adding complexity by having an additional entry.  Instead of having only one interface:  (buffer, size), you've now got two interfaces: (buffer, size) and (fixed-length-array).  If the writer knows they've got a fixed array they can use (buffer, sizeof(buffer)). If the writer knows they've got a more traditional buffer they can use (buffer, buflen). They know the single interface is there and they need to use it.

Imagine if the C language used that in their interfaces.  You'd have the current set of twenty-ish memory functions like memmov, memcpy, memcmp, and a duplicate version of all the functions for fixed-length arrays.

#### Share this post

##### Share on other sites

I guess what I meant to say is that rolling your own ways to check string length like this reads to me like a code smell / design smell kind of scenario.  If you created the array, you already know the size, so you can pass it around if you need it.

#### Share this post

##### Share on other sites
1 hour ago, Kylotan said:

Various fun hacks for this exist at StackOverflow.

41 minutes ago, frob said:

The reference trick in the StackOverflow site is the one I've seen several times over the years:


template<typename T> void f(T* const& c){ std::cout << "pointer\n"; }
template<typename T, size_t N> void f(T(&)[N]){ std::cout << "array\n"; }

Ah, yeah, thats what I've been looking for!

41 minutes ago, frob said:

The useful cases are almost non-existent.

24 minutes ago, trjh2k2 said:

I guess what I meant to say is that rolling your own ways to check string length like this reads to me like a code smell / design smell kind of scenario.  If you created the array, you already know the size, so you can pass it around if you need it.

Well, I should have been a bit more specific about my use-case: As I've mentioned I'm using my own StringView class, akin to std::experimental::basic_string_view.

Now that means that functions may have a signature as such:

bool Node::HasNode(sys::StringView strName) const
{
return m_mNodes.count(strName) != 0;
}

where it would have been eigther "const std::string&" (for me), or possible "const char*" / "const char*, size_t" before. This has many benefits, as such std::string_view has been proposed, but thats not the point of this post. Now in my code, I might use those functions as such:

const auto strName = node.Attribute("name")->GetValue();
widget.SetName(strName.ToString());

const auto isVariable = node.HasNode("IsVariable");
widget.SetIsVariable(isVariable);

const auto visibilty = core::VariableLoader::FromAttribute<Visibility>(node, "Visibility");
widget.SetVisibility(visibilty);

const auto isEnabled = !node.HasNode("Disabled");
widget.SetEnabled(isEnabled);

Not the every function above takes a sys::StringView. And thats pretty much where I applied my optimization. std::string_view would take a const char*, and call strlen. My StringView-constructor can take a static char-array, and directly deduce the size from this - thats the reason why I don't wanna do it by hand even though I technically "know" the strings size, its simple convenience so that I can call all those functions with string literals, but without having to take a copy or determine the size.

41 minutes ago, frob said:

As for the original problem here on the thread where you're trying to avoid taking the string length, that's not much of a benefit.  You're trying to simplify the interface, but instead you are adding complexity by having an additional entry.  Instead of having only one interface:  (buffer, size), you've now got two interfaces: (buffer, size) and (fixed-length-array).  If the writer knows they've got a fixed array they can use (buffer, sizeof(buffer)). If the writer knows they've got a more traditional buffer they can use (buffer, buflen). They know the single interface is there and they need to use it.

As you should see in my explanation, the function I proposed isn't really going to be part of an interface, its just an additional constructor for my StringView-class that internally calls it. I don't know if that makes it any better in your book, but I do see a compelling case for handling string-literals the way I do. Also the purpose of StringView is to offer a unified interface from many types (std::string, const char*, const char*+size) to a single const char*, size_t-pair. So I'd say my general notion is not totally wrong - the only difference I make is instead of treating every "const char*" as a nul-terminated string, I'm making a differentiation between static string-literals as part of a small optimization.

41 minutes ago, frob said:

Imagine if the C language used that in their interfaces.  You'd have the current set of twenty-ish memory functions like memmov, memcpy, memcmp, and a duplicate version of all the functions for fixed-length arrays.

Sure, adding 3-4 overloads for the same functions is surely overkill, I agree on that (in my case I should have mentioned how its intented to being used), but since we are talking about C-API functions - as you can read in my other thread:

there's actually a lot of issues going forward with modern C++ now that most C-style API functions only take nul-terminated C-strings; which wasn't a problem before but now with string_view this is actually limiting its usefulness. So I'd personally rather have atoi(const char*) and atoi(const char*, size_t) than being forced to make sure my strings are nul-terminated... but I thankfully don't have to support a large userbase with my API, so my expertise in that regard is rather limited.

EDIT: Anyways, the suggested "tricks" seem to work, even though for some reason I have to add a template type to my template-class ctor for it to work:

template<typename Type>
class StringView
{
template<typename Char, CheckIsCharPointer<Char> = 0>
BaseStringView(const Char* const& pString) : // still ambigous if I just use "Type" directly
BaseStringView(pString, StringLength(pString))
{
};

template<size_t Length>
constexpr BaseStringView(DynamicString<Length> pString) :
BaseStringView(pString, StringLength(pString))
{
};
}

But the problem seems solved, so thanks to all for helping me solve the problem I'm still rather happy to discuss the issues revolving around this; I just recently started to work with string_view so its certainly good to get more input on it.

## Create an account or sign in to comment

You need to be a member in order to leave a comment

## Create an account

Sign up for a new account in our community. It's easy!

Register a new account

## Sign in

Already have an account? Sign in here.

Sign In Now

• Advertisement