Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Slurps Mad Rips
Jan 25, 2009

Bwaltow!

quadreb posted:

So I'm going for a fresh build of the newest GCC:

gmp-4.2.4
mpfr-2.4.1
gcc-4.4.1

"make check" and "make install" on gmp and mpfr go fine, libraries are present and everything seems to be working.

Running ./configure in GCC fails however, and complains the mpfr isn't the right version. When I tell it where to find the .h file just created via the make install, it complains the gmp is the wrong version (which it doesn't do when I don't specify mpfr).


Any thoughts on how to proceed?

run ldconfig as root?

Adbot
ADBOT LOVES YOU

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

edit: (I ended up looking at the call stack, and none of what I said makes sense, so disregard this. I'll leave it here for posterity. Or something)

I have a brief question. Reading the documentation for Grand Central Dispatch implies that recursive calls to dispatch_sync result in a deadlock. Why then does this work? Wouldn't each subsequent dispatch_sync call wait for the next one to finish, but be in the "currently executing" position?

code:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <dispatch/dispatch.h>

void merge (int *a, int *b, int n) {
    int i, *x, *p, *q;
    x = malloc(n * sizeof (int));
    for (i = 0, p = a, q = b; i < n; i++) 
        x[i] = p == b     ? *q++
             : q == a + n ? *p++
             : *p < *q    ? *p++
             :              *q++;
    memcpy(a, x, n * sizeof (int));
    free(x);
}   
 
void merge_sort (int *array, int size) {
  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
    __block int *barray;
    __block int  mize;
    __block int* x = array;
    __block size_t s = size;
    if (size < 2)
        return;
    mize = size / 2;
    barray = array + mize;
    dispatch_sync(queue, ^{ merge_sort(x, mize); });
    dispatch_sync(queue, ^{ merge_sort(barray, s - mize); });
    dispatch_sync(queue, ^{ merge(x, barray, s); });
}
 
int main () {
    int a[] = { 38454, 39623, 29947, 82648, 77273, 1000, 69098, 97177, 43038, 
48953, 45947, 89301, 89736, 14941, 12279, 770, 6131, 59887, 31072, 3094, 87250,
5825, 60157, 10205, 13800, 91165, 19772, 5988, 38175, 12220, 98188, 16303, 86756, 
51959, 82797, 69907, 49190, 90491, 67198, 75181, 47536, 70602, 63988, 8498, 82438, 
34486, 72590, 3989, 8389, 44731, 72012, 89406, 74028, 20521, 1818, 17349, 41147, 
29965, 53048, 78803, 4, 65, 2, -31, 0, 99, 2, 83, 782, 1};
    int n = sizeof a / sizeof a[0];
    merge_sort(a, n);
  for (int idx = 0; idx < n; ++idx) {
    printf("%i ", a[idx]);
  }
  puts("");
    return 0;
}
output:
code:
-31 0 1 2 2 4 65 83 99 770 782 1000 1818 3094 3989 5825 5988 6131 8389 8498 10205 
12220 12279 13800 14941 16303 17349 19772 20521 29947 29965 31072 34486 38175 
38454 39623 41147 43038 44731 45947 47536 48953 49190 51959 53048 59887 60157 
63988 67198 69098 69907 70602 72012 72590 74028 75181 77273 78803 82438 82648 
82797 86756 87250 89301 89406 89736 90491 91165 97177 98188 
(please note I took this from the rosetta code wiki for merge sort, I only added the GCD calls. I am not responsible for that absolutely horrendous ternary clusterfuck within the merge function.)

Slurps Mad Rips fucked around with this message at 08:17 on Apr 18, 2011

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Paniolo posted:

C++11 implements what's called perfect forwarding meaning you can have a template function which passes its parameters onto another function in exactly the same state it received them (including lvalue/rvalue-ness.) A function that implements perfect forwarding (for one argument) looks like this:

code:
template <typename T>
void Foo(T&& t)
{
   Bar(std::forward<T>(t));
}
There's a good explanation here: http://thbecker.net/articles/rvalue_references/section_08.html

The bug is that Visual C++ doesn't actually support perfect forwarding since it chokes when you try to pass a function pointer through.

Have you tried using an explicit call to std::move? I seem to recall VS2010 not doing any of it automatically because at the time of release, the corner cases and a few other issues had yet to be handled.

(I'm probably wrong though)

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

I'm doing a bit of an experiment where I try to avoid the C preprocessor in my platform specific code as much as possible. I'm relying on SFINAE and a few enums which hold values of 0 or 1 depending on compiler or platform information (e.g., "compiler::msvc").

So, for example, I do something like this:

code:
template <typename T, typename U> struct combo {
  typedef typename std::conditional<
    sizeof(T) == sizeof(U),
    T,
    void
  >::type return_type;

  typedef typename std::conditional<
    std::is_same<T, return_type>::value,
    T,
    U*
  >::type param_type;
};

template <typename T, bool=compiler::msvc> class swap;

/* gcc/clang */
template <typename T> class swap<T, false> {
  typedef typename combo<T, uint64_t>::return_type qword;
  typedef typename combo<T, uint32_t>::return_type dword;
  typedef typename combo<T, uint16_t>::return_type word;

  typedef typename combo<T, uint64_t>::param_type qparam;
  typedef typename combo<T, uint32_t>::param_type dparam;
  typedef typename combo<T, uint16_t>::param_type wparam;

public:
  static inline qword call(qparam val) { return __builtin_bswap64(val); }
  static inline dword call(dparam val) { return __builtin_bswap32(val); }
  static inline word call(wparam val) {
    return ((val & 0xFF00) >> 8) | ((val & 0x00FF) << 8);
  }
};

/* msvc */
template <typename T> class swap<T, true> {
  typedef typename combo<T, uint64_t>::return_type qword;
  typedef typename combo<T, uint32_t>::return_type dword;
  typedef typename combo<T, uint16_t>::return_type word;

  typedef typename combo<T, uint64_t>::param_type qparam;
  typedef typename combo<T, uint32_t>::param_type dparam;
  typedef typename combo<T, uint16_t>::param_type wparam;

public:
  static inline qword call(qparam val) { return _byteswap_uint64(val); }
  static inline dword call(dparam val) { return _byteswap_ulong(val); }
  static inline word call(wparam val) { return _byteswap_ushort(val); }

};

template <typename T> T bit_swap(T val) { return swap<T>::call(val); }
So far it compiles fine in clang from xcode 4.2, gcc 4.7 trunk, and msvc 10. However, only clang seems to freak out when I use the global scope resolution operator in the msvc call functions (of which the struct and functions shouldn't ever be instantiated, since compiler::msvc = 0).

code:
static inline qword call(qparam val) { return ::_byteswap_uint64(val); }
results in a compile time error. I was under the assumption that the contents of a function would not be needed unless it was actually considered to be a positive match, and even then could simply exist elsewhere.

My question is: Is this intended behavior, a result of clang being greedy with it's instantiations, or an actual legitimate bug?

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

rjmccall posted:

It's intended and correct behavior: clang is type-checking your template definitions, which it's allowed to do when all the relevant code is totally non-dependent. We have a pretty good write-up of this on our compatibility page.

:doh: I was looking for that section so I wouldn't have to post here, but I just couldn't find it.

rjmccall posted:

What's happening here specifically is that unqualified lookup finds nothing for _byteswap_uint64. That's not always a problem for a function call with dependently-typed arguments, as you have here, because argument-dependent lookup can still find functions from associated namespaces of the argument types — except that ADL is suppressed when you add the scope-resolution operator. When you do that, Clang can deduce that there are no valid instantiations of this code, so it complains.

You would get the same error from an EDG-based frontend in strict mode.

ETA: incidentally, it turns out that, even without the scope-resolution operator, there are no valid instantiations of this code in a standards-compliant compiler: during instantiation, the argument types to the calls are observed to be primitive types and so don't have any associated namespaces, so ADL is a no-op. Of course, in MSVC it would work because unqualified lookup actually finds the intrinsic.

Awesome. I was wondering if the ADL being suppressed was supposed to happen or not.

However on the subject of there being no valid instantiations, wouldn't the default bool set to
template <typename T, bool=false> swap; result in no instantiation of the true specialization taking place ever, and it being 'optimized' away? Or does this come down to implementation specific details?

edit: nevermind

clang compat posted:

unqualified names like DoThis and DoThat are looked up when the template Derived is defined, not when it's instantiated.

Though I'm still not entirely sure why this code works now that it's becoming fairly apparent that it shouldn't :/

Slurps Mad Rips fucked around with this message at 09:57 on Jan 24, 2012

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

rjmccall posted:

As long as you can pass at least one argument with a dependent type, you'll be fine, because that will let you avoid warnings from trying to check the wrong compiler's intrinsics. You can always make a type spuriously dependent using a class template that completely ignores all its template parameters. You'll have problems if you ever need to use an intrinsic that takes zero arguments, though.

Oh! Ok, that makes a lot more sense. Thanks for your help :)

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Paniolo posted:

The CUDA Toolkit includes nVidia's OpenCL libraries. I'm pretty sure you have to compile against the hardware vendor for the target machine, so if you need to support both nVidia and ATI cards you'll have to provide binaries for both, or provide source and have your customers build it themselves.

If you're on Windows exclusively you could look into DirectCompute (or C++ AMP, which is built on it) which will work without recompilation on both vendors.

If this is just a learning project then just grab the SDK from your video card's manufacturer and go nuts.

Most of the vendor's out there follow the Installable Client Model (icd) extension, which allows you to query all available opencl platforms on a given machine, whether they are from the same vendor or not. You simply need to install their runtime for it to work.

You can read more about it here. It gives a few examples, but AFAIK Intel, AMD, and Nvidia all follow the ICD.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

That Turkey Story posted:

The game industry is hosed.

Seriously, I used the phrase RAII in a sentence 3 weeks ago to explain how something worked, and none of the people in the room knew what I was talking about. These are people who have apparently been writing C++ since before it was standardized. It's like someone heard a bad thing from someone else who a) doesn't understand how a language feature works (don't use vtables!) b) hasn't paid attention to any modern advancements (Templates bloat your code!) or c) just writes C with objects. There's also the occasional d) Don't use the standard library it is slow! Let's spend a shitload of time writing our own container classes and allocators that we'll offload to junior programmers who don't know what they are doing.

By the way, that 'templates bloat your code' quote, was stated by a former Starcraft 2 tools programmer.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Suspicious Dish posted:

The reason EASTL was written was specifically for embedded targets. They openly went into the tradeoffs they made in their system in the paper they released. It wasn't ignorance -- the standard library wasn't working for them in some specific situations, so they wrote something that was a bit more up to their needs.

What really bothers me is an outright dismissal of an idea, instead opting to instead quote a one-liner and generalize it beyond what it should be.

There are reasons that the STL may not be appropriate to all tasks, regardless of how "unthinkable" the idea is.

No no no, when I say the standard library, I don't mean the STL. I mean the whole. drat. thing. They were passing nostdlib and nostdinc to the compiler. I understand the EASTL was written for that. Granted they lied in their paper and used MSVC with the checked iterators and other debug features on, but at least because of the EASTL we now have stateful allocators in C++11.

rjmccall posted:

Do not take this as an absolute endorsement of the position, but templates can definitely bloat your code. libc++'s std::sort, for example, clocks in at around 12K per instantiation. Using something like qsort is slower, but it's much more compact.

There's a difference between shouting to the rooftops "Don't use templates they bloat your code!" without telling people why they should avoid it in a specific circumstance and people just mindlessly restating something someone told them in 1999. Which is the latter 99% of the time in the game industry.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

netcat posted:

Here's something I thought was kinda strange. The following does not compile:

code:
#include <vector>
#include <iostream>
 
struct foo
{
 int x;
 char name[8];
};
 
 static std::vector<foo> b = {
    { 1, "a" },
    { 2, "b" }
 };
 
int main()
{
    for (auto it = b.begin(); it != b.end(); ++it)
    {
        std::cout << it->name << "\n";
    }
    
    return 0;
}
prog.cpp:13:2: error: could not convert ‘{{1, "a"}, {2, "b"}}’ from ‘<brace-enclosed initializer list>’ to ‘std::vector<foo>’

http://ideone.com/UlCXDN

But if I instead use { 'a', '\0' } when creating the char-arrays, it compiles just fine. Why does it work like that?

This is a bug with GCC, though all is not as it appears. If we change the std::vector<foo> to a std::array<foo, 2>, it will compile (We add the extra braces for aggregate initialization that std::array requires of course). However, removing the = sign shows a different set of compiler errors:

code:
error: no matching function for call to 'std::vector<foo>::vector(<brace-enclosed initializer list>)'
And then it begins to dump some SFINAE to us (i.e., "These are the constructors I can choose from, but you gave me this!"). Looking closely at the output, we'll see that it doesn't ever refer to the list of brace enclosed initializers as anything but (When in an ideal world it would say it was a std::initializer_list<foo> because that's what we want to create). Basically, gcc is trying to infer the constructor it needs to call at a very shallow level, and doesn't try to treat these initializers as foos, but just raw dumb unnamed brace enclosed initializers. If we are a little more explicit for GCC, it will take our arguments for the proper constructor:

code:
static std::vector<foo> b {
   foo { 1, "a" },
   foo { 2, "b" },
};
Which results in a std::initializer_list<foo> being built.

This is definitely a bug, just not the bug it seems to be. I've run into this with a recursive variadic unrestricted union-like variant class I was writing for a while. Huge PITA, and it basically destroys the point of having a variant in the first place. Bit of a show stopper. :(

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

ratbert90 posted:

Why can't people just use enums and call it good? :smith: Just ignore the vast libraries that make life easy for you in C++!

Use enums for everything!

code:
enum class which {
  one,
  two,
  three
}

void cxx11_owns (which) { }

int main () {
  cxx11_owns(which::one);
}
Wait a second.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

xgalaxy posted:

I was a big fan of premake but development is slow.
I just bit the bullet and started using cmake myself.
I hate it, but at least it works.

The key to writing cmake build scripts (so that you don't lose your sanity) is to not use any programming construct outside of an if-endif (and try not to havemore than one level of nesting) unless you are writing a new feature, in which case Dijkstra save you. Once you get used to writing one command per line, it becomes a lot easier to read your own build script to decipher just what is happening when you mess up (which you will)

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Jerry SanDisky posted:

So is there a good "Cmake for people with severe mental retardation" tutorial other than the official one? I'm coming from Autotools, so anything that is friendlier than that will work.

Unfortunately, not really. There's the CMake Wiki, and the documentation. Once you understand the language that *should* be enough to get you moving forward (it just becomes a matter of reading the documentation and sometimes tinkering with configure runs to make sure it does what you think it does). The language tutorial they have is decent enough for what it is, and the language works almost like tcl (I say almost because you can't put hyphens in your function/macro names).

Also, all the commands and macros are case insensitive, so if you see a tutorial or script doing

code:
IF(SOME_VAR_THAT_IS_DEFINED_AND_IS_VERY_LARGE)
 SET(SOME_MORE_STUFF_BECAUSE_IF_IT_AINT_CAPS_IT_AINT_SHIT )
ENDIF()
You can ignore the upper case commands and it will work just fine, and be a heck of a lot more readable. Someone (hopefully not me) should write a better CMake tutorial, because as it is it's hard to hit the ground running without any experience with it.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

ratbert90 posted:

I generally use caps with macros and enums only. Local variables get lowercase, and objects get Uppercase (Object.ButtFarts). It's all incredibly consistant so it's easy to see what's what right away.

This is cmake, not c or c++. It has two types. String, and string with a semicolon, which denotes a list. I'm not a huge fan of the language and tons of other people aren't either. Maybe when they move to 3.0 they'll use a real language. But they are too scared to break backwards compatibility.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

astr0man posted:

I use lowercase for cmake operators and all caps for variables. I guess I only do it that way out of habit from writing shell/environment variables and crap, but I think it makes it slightly easier to differentiate between variables and filenames at a quick glance.

I do this as well and it's considered "the write thing to do" by the community at this point.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Valtis posted:

Found a solution to this:

This seems to be issue only if I use static linking with libgcc\libstdc++; if I remove one or both of -static-libgcc and -static-libstdc++ flags, exceptions start working again. GCC documentation on the subject does say that "There are several situations in which an application should use the shared libgcc instead of the static version. The most common of these is when the application wishes to throw and catch exceptions across different shared libraries. In that case, each of the libraries as well as the application itself should use the shared libgcc.", however I'm not throwing across libraries so I'm not sure why there is an issue here.

Was boost.filesystem compiled with the same -static-libgcc and -static-libstdc++ flags?

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Sintax posted:

It works but since this is C++ I know there's a problem with the approach. Is my use of global functionality abusive? Is this creating a bunch of copies of _pos? Is there a better way to access single-instance classes?

The static local function variable :eng101:

code:
class Mouse {
  Mouse();
public:
  static Mouse& ref() {
    static Mouse instance;
    return instance;
  }
};

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

seiken posted:

The problem was the the poster didn't understand why a copy constructor would be needed at all. The distinction is the = used in the variable declaration.
C++ code:
auto archive = Archive(archiveFilename);
C++ code:
Archive archive(archiveFilename);
These two statements, in most cases, do the same thing. But what the first really does is to create a temporary Archive and then uses it to copy-construct archive, rather than directly constructing archive. I think sometimes this may be optimised away depending on how simple the type is, but nevertheless if you use the first statement the copy-constructor must exist and be accessible.

That is incorrect. That first expression should use a move constructor at most, and a default initialization at least.
(as the expression on the right is an rvalue) unless the compiler being used is some visual studio version in which case ignore me, as visual studio doesn't follow the new standard.

EDIT: wow, I double quoted somehow?

Slurps Mad Rips fucked around with this message at 20:32 on Sep 10, 2013

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

That Turkey Story posted:

It is still allowed to be optimized away in C++03 and C++11, and compilers do so (it also doesn't matter how complicated the type or its copy/move is). The appropriate constructor still needs to be able to be called though.

What? Lambdas are copyable. In fact, just about every time you use them you are copying them, since most proper algorithms take the function object by value.

No. Seiken really is correct. A compliant compiler is allowed to optimize away the copy or move operation and construct the object in place.

I somehow managed to post the one response that I realize was wrong (about the lambdas). I could have sworn I deleted it (was posting from the awful app), but it went through anyhow. That explains the double quote.

I know they can optimize it away, but I believe I had read the message where most cases wasn't in the message (I definitely don't remember it being there). Basically I hosed up, ignore what I said :v:

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Hughlander posted:

What's the state of Clang on win32 these days particularly when it comes to it's standard library? I understand the library isn't finished being ported yet, can I substitute out the one in Visual Studio 2012 or 2013 when it comes out to have a mostly up to date C++11 library? This is for porting something that already runs under Linux/OS X to Windows.

They're working on a LLVM for windows installer at the moment: http://llvm.org/builds/

However it's not entirely able to use all of Microsoft's standard library (for instance you can't use any <*stream> headers).

If you're porting something to Windows from Linux/OS X, I'd recommend using the MinGW-builds 4.8.1 SEH POSIX version. It implements all of the standard, uses SEH for exception handling, and the all of the std::future stuff actually works (it currently doesn't with MinGW Win32 threads builds, or at least it didn't in 4.8.0 and I didn't see any changes related to that in 4.8.1)

I've yet to run into a compatibility issue with it when moving from clang to mingw and back, outside of perhaps libstdc++ missing one or two constructors within container classes (specifically allocator.uses.construction)

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

bobua posted:

This might be more of a general programming question, but I'm focused on c++.

I have no concept for(and trouble googling for) applications 'communicating,' apart from one app writing to and the other app reading from an actual file. What are some terms I should google?

Just as an example, to help illustrate my question... Let's say I have a custom object in my app, and I want another running instance of that app(or another app I've written) to access that object without writing it to disk somewhere?

Search for Inter-Process Communication. Usually people just refer to it as IPC.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

So brief question on the subject of types and unions in C++11. I'm attempting to pack several types to be no more than 16 bytes each (memory is extremely limited) on a 64-bit platform. These types are recursive (that is the union-like class that stores these possible values is in fact a possible object located within the classes it holds), so it is best to save space here, as otherwise I end up wasting 7 bytes per boost::variant. Additionally, the packed attribute breaks for GCC, and clang doesn't like it either for some reason, so I'm taking a different route.

So far each type that isn't an number looks something like

code:
struct type {
  std::unique_ptr<void> ptr; // this is actually a guaranteed type, not a void*
  std::uint32_t cap : 28; // capacity
  std::uint32_t len : 28; // length
};
And since the available types will never be more than 8, I figured I could pad the last byte with a std::bitset<8>, and have the bitset bits be the tag for the union. However, if I stick the bitset outside of the union, I end up with a 24 byte aligned structure (wasting, once more, 7 bytes)

My question is, if I were to add the bitset to each type (and wrap the integral types so that they are properly aligned), is it legal to access the 'bitset' member of each type directly, whether that specific type has been initialized? I was able to find this stackoverflow which gave me some hints that in this case, all the types would in fact meet the requirements in that the std::bitset<8> was always initialized and could therefore be accessed regardless of type as a member, and not invoke undefined behavior.

For safety's sake I'm going to assume no, as the compiler could technically reorder each type's location of std::bitset, and then I'd be boned, but I would like just a little bit of confirmation.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

FamDav posted:

types that can go into unions are PODs, which guarantees they have the same memory layout as C. If your bitset is at the start of each type, it will be accessible from all types when type-punning.

EDIT: to be pedantic, c++ unions accept some things which aren't PODs. Whatever your types are probably PODs

EDIT2: So you were unable to get something like

C++ code:
struct tagged_union {
	enum class TYPES : char { T0 = 0, T1 = 1, etc... };
	union {
		type0;
		type1;
		etc..
	};
};
working with minimal size?

That was a data example, but these types are not PODs, nor are they trivial or standard layout. Additionally, I'd prefer to put the bitset at the end as everything else is taking up 15 bytes at the front. I'm worried about type punning within a union-like class with the relaxed C++ rules regarding unions.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

SAHChandler posted:

That was a data example, but these types are not PODs, nor are they trivial or standard layout. Additionally, I'd prefer to put the bitset at the end as everything else is taking up 15 bytes at the front. I'm worried about type punning within a union-like class with the relaxed C++ rules regarding unions.

Disregard my previous message, I forgot I have to support custom allocators, so this whole thing falls apart :v:

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

GrumpyDoctor posted:

It's possible that there's something you can set to make it not do that, but I wouldn't hold my breath.

The option to force msvc to disable language extensions is /Za. However it's use is not recommended because it breaks all kinds of poo poo and they stopped testing the standard library with it since VS10.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Subjunctive posted:

Is that the case only if iso646 is included transitively and nothing is redefined? (In the C case; they're part of the language in C++ but not C IIRC.)

Edit:

Per http://en.wikipedia.org/wiki/C_alternative_tokens#C.2B.2B


Hmm.

If you pass /Za to MSVC, you can use these operators without requiring the header. However adding /Za results in compiler extensions being disabled. it's also pretty buggy and isn't being actively tested. It hasn't been deprecated either.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Paniolo posted:

I'm having trouble understanding why this doesn't work:

code:
template <typename TRange>
class is_range
{
public:

    template <typename T>
    static auto test(T&) -> decltype(begin(T));

    static void test(...);

    static const bool value =
        !std::is_same<decltype(test(std::declval<TRange>())), void>::value;
};
It's always false, and if I call the test function directly:

code:
std::vector<int> vec;

is_range<decltype(vec)>::test(vec);
The linker error I get indicates it's resolving to the ... overload instead of the template function. However, the following compiles just fine:

code:
std::vector<int> vec;

decltype(begin(vec)) iter = begin(vec);
So I'm missing something.

You forgot to make the true check look like decltype(begin(declval<T&>())) for its return type. You're basically passing a type directly to begin otherwise causing it to fail.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

The Laplace Demon posted:

Just use template<typename T> using ptr = T*;

ptr<int> a, b; is literally impossible to mess up.

It also lets you easily define function pointers. ptr<int(int)> f

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

The Laplace Demon posted:

Where's your sense of adventure? It looks like a function pointer as much as unique_ptr<int(int)> and shared_ptr<int(int)> do. But I'm probably corrupted from extended exposure to function<R(A...)>.

Also, it makes writing functions returning function pointers a breeze. Compare the following:
C++ code:
bool (*foo(int bar, int baz))(const char*, const char*);
void (*(*quux(int a, const char* b))(int, int))(const char*, const char*) { return &foo; }

ptr<bool(const char*, const char*)> foo(int bar, int baz);
ptr<ptr<void(const char*, const char*)>(int, int)> quux(int a, const char* b) { return &foo; }
ptr<T> is more verbose, but I think the uninitiated to the horrors of function pointer syntax actually stand a chance at writing a function definition correctly.

You could also use std::reference_wrapper<T(Args...)> :v:

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

The Laplace Demon posted:

I'm genuinely a fan of observer_ptr from MNMLSTC Core

Thanks for the plug :)

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Gerblyn posted:

Multiple Inheritance in C++ is pretty messy, and should be avoided if at all possible. You can get some really weird behavior with forward defines and casting and things. I mean it does work, and if you're careful you probably won't run into issues, but the few times I've used it in the past have ended in disaster with me swearing never to do it again.

Multiple public inheritance can get messy. Multiple private inheritance is pretty hard to screw up.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

rjmccall posted:

You mean a magic bottom type, and IIRC the answer is that it didn't used to be, but C++14 (?) added some hacks to conditional expressions around it.

Using a throw in an expression was mentioned in C++11 I believe, otherwise it would be really hard to error out of constexpr functions. Most stuff like string_view must be implement several functions in terms of the ternary with a throw of implementing it in C++11 instead of C++14.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

OneEightHundred posted:

Since I'm starting to set up a slightly-built-up and template heavy VC++ pboject on Clang right now, I figured I'd share some of the hilarity from something that's barely even over a few thousand LOC to demonstrate how easy it is to just fat-finger something that MSVC will happily march through.

This is aside from the usual much better known case of two-stage lookup failures, which I actually had none of aside from missing a prototype in one case, mostly by being super careful about it.

code:
template<class T>
void DoSomething() { DoSomethingElse() }

template<>
struct MySpecialization<::Something> { };

template<class T>
typename void DoSomething();

template<class T> void MyFunc();
template<class T> void MyFunc<T>() { }    
1.) MSVC ignores the missing ";" syntax error unless it has to instantiate the function. :lol:
2.) <: is a digraph. :mad:
3.) typename void is illegal.
4.) MSVC thinks that's a definition, Clang thinks it's a partial template specialization of a function.

<: is not a digraph when it's used in templates as a smiling spider (i.e., <:: ). This was added in C++11. Depending on your version of MSVC the behavior will differ (between incorrect and correct behavior).

You can see more regarding this here. (Scroll down to digraphs and trigraphs)

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

OneEightHundred posted:

No, that code compiles in MSVC, it's Clang that hates it. I might have to upgrade Clang then, but apparently that feature wasn't supported in 3.5.2 and its current state is "Unknown." :v:

That huge list contains a set of defects regarding the C++11 standard (some of which were brought up in 2010) and the solution to the issue of "well what happens if I write `<::`" is in fact mentioned here (NOTE: the whole page may not load). Because clang does implement C++11 (and is mostly conforming as a result of a few parser bugs. Looking at you deleted template declaration failing when specialized), I reckon most of these are marked as unknown because they are simply implemented and fixed and are mentioned in a specific document (namely a standard such as C++11 or C++14)

Using http://gcc.godbolt.org I was able to get clang 3.0 through 3.7 to accept a global scope argument to a template.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

roomforthetuna posted:

Yesterday I learned of this cool thing:
code:

auto poop = +[]int(int butts) {return butts * 2;}
That unusual + makes poop a simple old-school function pointer rather than a std::function with the overhead that entails. Neat!

a lambda does not a std::function make. Each lambda is its own unique type as if you had written a C++03 function object. There is no overhead for declaring a lambda beyond any captures you make.

a std::function uses type erasure to, internally, create a unique implementation object. And assign that to an internal base pointer providing overhead via a call to a virtual function (which can be reduced with devirtualization techniques in some compilers though you shouldn't bet on it always happening).

The only time that the C++ stdlib ever takes syntax and produces a special named type is with typeid (std::type_info).

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

leper khan posted:

^a good post. :five:

Not using std::string (or wstring, ..) has been a pretty strong leading indicator that I'm going to be dealing with a house of horrors. At least for projects started in the past 5-ish years. It's very easy for people to write things that are less performant and more broken when they think dealing with strings is easy and people who wrote the STL are obviously dumb because they read something like that but far more nuanced on the internet once.

As with all things, it's not a problem until you've benchmarked. If you aren't in a place where you can benchmark and you don't have a suitable replacement with several years of industrial use behind it, you have better things to be working on than std::string being too slow for your non-extant application.

string_view is definitely worth having but it's really easy to gently caress up an implementation if you don't even know what a quarter of the std::string functions do and have never tried to implement them yourself (and boost::string_ref didn't exist yet :v:)

(It's also easy to adapt string_view if you're stuck with someone's bespoke string type)

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

Volguus posted:

I am using in one of my projects the crow http library (https://github.com/ipkn/crow) . My compiler (gcc 6.2.1) is complaining about this code from the library:

code:
uint64_t remaining_length_{0};

....//reading 2 bytes from the network....

remaining_length_ = ntohs(*(uint16_t*)&remaining_length_);
Warning given: "warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]"

How should the 2 byte network to host conversion be done to avoid that warning and still be correct?

Use memcpy.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

leper khan posted:

clang, vim, and at least for small/mid size projects youcompleteme is good, but i'm not sure if it works well with large projects. i also like syntastic.

lldb/gdb or whatever graphical frontend thereof you prefer for a debugger

We have a several million line code base at work and not a single person uses an IDE. 5 vim users, and one guy using emacs.

I also don't personally use an autocompleter because I've discovered 9/10 times it just gets in the way and slows me down from what I want to do. A "go to definition" tool by itself is more useful.

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

leper khan posted:

besides 9/10 times you're doing twee garbage to try to ICE a compiler. of course completion is going to have trouble :v:

they've gotten a lot more stable nowadays. I think I've only gotten 1 ICE this past year, and only about 4 the year before :v:

Adbot
ADBOT LOVES YOU

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

leper khan posted:

I had to pull out the standard to correct him. Didn't get the job. :shrug:

If I had a dollar for every time this happened I wouldn't need to hunt for jobs, I'd just interview all the time.

Except the one time I blew a dudes mind by telling him about lambdas and he was afraid. "So you can just define a function... anywhere INSIDE another function?!" That one was just fun.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply