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
netcat
Apr 29, 2008
What the heck is going on here.

I have a makefile like this:
code:
CC = g++
FLAGS = -std=c++0x
CFLAGS = -Wall
LIBS = -lncurses

TARGET = Game
SRC = $(shell find . -type f -name \*.cpp)
OBJ = $(SRC:.cpp=.o)

all: $(TARGET)

clean: $(shell rm -rf *.o)

$(TARGET): $(OBJ)
    $(CC) $(FLAGS) $(CFLAGS) -o $(TARGET) $(OBJ) $(LIBS)
.cpp.o:
    $(CC) $(FLAGS) $(CFLAGS) -o $@ -c $<
Building using this makefile produces incredibly weird bugs (like objects not being copied properly, stuff like that) in my finished executable while just doing:
g++ -std=c++0x -Wall -o Game *.cpp -lncurses
everything works as expected.

I'm doing a Linux port of a thing I've had working in Windows for a long time. I haven't been working with raw makefiles like this in forever but this just seems weird

Adbot
ADBOT LOVES YOU

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
You can delete all those rules, since make has implicit rules by default. Just keep LIBS, CFLAGS, and do:

code:
all: $(TARGET)

clean:
    rm $(OBJ)
    rm $(TARGET)

$(TARGET): $(OBJ)

netcat
Apr 29, 2008

Suspicious Dish posted:

You can delete all those rules, since make has implicit rules by default. Just keep LIBS, CFLAGS, and do:

code:
all: $(TARGET)

clean:
    rm $(OBJ)
    rm $(TARGET)

$(TARGET): $(OBJ)

Hmm OK. Anyway, my original problem went away with a later version of GCC. I guess it might've been a compiler bug

fritz
Jul 26, 2003

netcat posted:

Hmm OK. Anyway, my original problem went away with a later version of GCC. I guess it might've been a compiler bug

It's never a compiler bug.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

fritz posted:

It's never a compiler bug.

but god, when it is, does it take a long time to find out

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Times it is a compiler bug:

  • You're using literally anything but gcc / clang. See: MSVC, SunCC, Intel C compiler, CodeWarriors, the BREW SDK (one of the worst things I've used), countless "C+" compilers for random Japanese embedded systems that don't work, the Borland tooling, HP aC++, why are there so many compilers??? And how the hell did IBM write five of them during its lifetime?
  • Sometimes when you're using clang. Because it's still in beta.
  • That time that you passed -O3 and gcc completely farted itself.
  • You're compiling for something that isn't x86-64. Like ARM, ARC, PPC, SPARC, or even i386.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Suspicious Dish posted:

Times it is a compiler bug:

  • You're using literally anything but gcc / clang. See: MSVC, SunCC, Intel C compiler, CodeWarriors, the BREW SDK (one of the worst things I've used), countless "C+" compilers for random Japanese embedded systems that don't work, the Borland tooling, HP aC++, why are there so many compilers??? And how the hell did IBM write five of them during its lifetime?
  • Sometimes when you're using clang. Because it's still in beta.
  • That time that you passed -O3 and gcc completely farted itself.
  • You're compiling for something that isn't x86-64. Like ARM, ARC, PPC, SPARC, or even i386.

  • you're cross-compiling
  • the compiler is more than 3 years old

Schmerm
Sep 1, 2000
College Slice
Okay, I have a C++ RTTI conundrum. I need to test whether class A is a subclass of class B without having instances of either class lying around (so I can't just dynamic_cast).

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Schmerm posted:

Okay, I have a C++ RTTI conundrum. I need to test whether class A is a subclass of class B without having instances of either class lying around (so I can't just dynamic_cast).

This seems unrelated to RTTI, since you can get what you need using entirely static information. You could probably just use is_convertible to check whether an instance of A would be implicitly convertible to an instance of B, without actually needing to have an instance on hand.

pmchem
Jan 22, 2010


I once ran across a compiler bug in a random number generator, that caused my program to crash. That was a fun one tracking down.

ullerrm
Dec 31, 2012

Oh, the network slogan is true -- "watch FOX and be damned for all eternity!"

Don't forget STL/libc bugs, which aren't technically part of the compiler, but might as well be. The major containers (list/vector/deque/map) and most common functions in <algorithm> are usually bug-free, but the rest is hit and miss, for both GCC/Clang and MSVC.

Especially for C++11 content. Right now, both compilers' implementations of <functional> are basically garbage. <type_traits> was garbage until recently as well, because both compilers relied on internal hooks to implement things like is_convertible, and didn't always get it right.

pseudorandom name
May 6, 2007

What's wrong with functional?

Schmerm
Sep 1, 2000
College Slice

Jabor posted:

This seems unrelated to RTTI, since you can get what you need using entirely static information. You could probably just use is_convertible to check whether an instance of A would be implicitly convertible to an instance of B, without actually needing to have an instance on hand.

Cool! All these type query utility thingies are pretty useful. Unfortunately, I can't use is_convertible in my case :( I'm creating a facility to register a C++ class and bind it with some scripting language stuff. Each time I register a class, I want to scan through all the already-registered classes and see if the incoming class is a subclass of any of them, and use that information to update the ordering/relationship of the registered classes. There's dynamic behaviour in there.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Schmerm posted:

Each time I register a class, I want to scan through all the already-registered classes and see if the incoming class is a subclass of any of them, and use that information to update the ordering/relationship of the registered classes.

It seems incredibly silly to me, but std::type_info (what I would have used) does not support this

e: not with the standard std::type_info at least, of loving course this information is available to the runtime environment for exception handling

e2: do you have any code to show us?

hackbunny fucked around with this message at 01:09 on Jan 16, 2015

pseudorandom name
May 6, 2007

You're asking for reflection, and C++ doesn't support that.

ullerrm
Dec 31, 2012

Oh, the network slogan is true -- "watch FOX and be damned for all eternity!"

Schmerm posted:

Cool! All these type query utility thingies are pretty useful. Unfortunately, I can't use is_convertible in my case :( I'm creating a facility to register a C++ class and bind it with some scripting language stuff. Each time I register a class, I want to scan through all the already-registered classes and see if the incoming class is a subclass of any of them, and use that information to update the ordering/relationship of the registered classes. There's dynamic behaviour in there.

This sounds like runtime reflection, honestly. Most of typeinfo won't help you (it's mostly compiletime operations), and there's nothing in C++ RTTI (or Boost::TypeIndex) that can support this -- you can identify what class a pointer is, and distinguish classes using typeid::hash_code, but you can't determine inheritance.

You're going to have to implement this yourself.

Falcorum
Oct 21, 2010
On the plus side, there's a couple reflection proposals for C++17 so in a couple years you might have access to them (or a decade or so if you're using MSVC).

Dren
Jan 5, 2001

Pillbug

Schmerm posted:

Cool! All these type query utility thingies are pretty useful. Unfortunately, I can't use is_convertible in my case :( I'm creating a facility to register a C++ class and bind it with some scripting language stuff. Each time I register a class, I want to scan through all the already-registered classes and see if the incoming class is a subclass of any of them, and use that information to update the ordering/relationship of the registered classes. There's dynamic behaviour in there.

How are you having this work, exactly?

What is the facility to register a C++ class and bind it with some scripting language stuff? Is it a C++ program? A program in the scripting language? A C++ module for a scripting language program? What is the scripting language?

You said you want to scan through already registered classes for inheritance relationships upon registering a class. How is a class registered? Does registering a class happen at C++ runtime or via scanning the source or what?

The whole idea of registering a C++ class you know nothing about and don't have an instance of is weird to me. If you don't know what it is you can't call any methods on it or use it in any way. If you don't have an instance of it then you've got to be scanning the source, right? Because where else would you even get a class to register?

nielsm
Jun 1, 2009



Dren posted:

You said you want to scan through already registered classes for inheritance relationships upon registering a class. How is a class registered? Does registering a class happen at C++ runtime or via scanning the source or what?

The whole idea of registering a C++ class you know nothing about and don't have an instance of is weird to me. If you don't know what it is you can't call any methods on it or use it in any way. If you don't have an instance of it then you've got to be scanning the source, right? Because where else would you even get a class to register?

I imagine it's some template stuff. A factory class that takes a worker class as template parameter, and you then make globally initialized instances of those templates factories that register themselves.

C++ code:
class DongBase;

class BaseFactory {
  std::map<std::string, BaseFactory*> factories;
protected:
  static void register_factory(std::string n, BaseFactory *f) { factories.push_back(std::make_pair(n, f)); }
  virtual DongBase * internal_create() const = 0;
public:
  DongBase * create(std::string name) const {
    auto f = factories.find(name);
    if (f != factories.end()) return f->internal_create();
    else return nullptr;
  }
};
template<class T>
class DongFactory : BaseFactory {
protected:
  DongBase * internal_create() const override { return new T(); }
public:
  DongFactory(std::string name) { register_factory(name, this); }
};

nielsm fucked around with this message at 11:57 on Jan 17, 2015

Dren
Jan 5, 2001

Pillbug
If the classes are determined at compile time, as they would be with templates, a code inspection tool could be used to work out the inheritance relationships then poop out a Config file or something that has them all. Something like ctags or doxygen.

nielsm
Jun 1, 2009



Dren posted:

If the classes are determined at compile time, as they would be with templates, a code inspection tool could be used to work out the inheritance relationships then poop out a Config file or something that has them all. Something like ctags or doxygen.

Yep the only way to have a (polymorphic) runtime object in C++ that represents a class rather than being an instance of that class, is to have a factory similar to that. And since you're already bothering with making your own reflection-like thing there you may as well also bake in some extra metadata.

If you e.g. need some kind of ordering on the classes registered with that kind of factory, you could do it by having an additional, optional parameter to the factory instance constructor and to the factory base registration function, that takes the registered name of the base class the registered class inherits from. It's not automatic, by any means, but it can work.
You could also try to bake the information into the classes being registered, with some static members of some sort, and reference those in the factory classes.

(I suppose you could theoretically also try to get a pointer to the vtable of a class and work with that directly, but then you're getting into implementation-defined territory and definitely won't be portable.)

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Getting a vtable pointer is always going to involve undefined behavior.

The unportable but still valid solution would be to look up the layout of class type_info objects on your platform(s), redeclare that in your own code, and using that to dynamically query the bases of the class. If you're using gcc/clang, you can just steal the declarations from libc++abi's private headers; they should work regardless of what C++ library you're actually using, because the layout is dictated by the ABI. (Don't call the extra virtual functions unless you're sure you're using libc++abi, though.)

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
glibmm does this through horrible hacks to register subtypes with the GType type system. You can steal their magic if you want.

Schmerm
Sep 1, 2000
College Slice
I create Lua bindings for C++ classes. Each class must be explicitly registered with a function call that looks something like:

code:
register_class<CPPClass>("ClassNameInLua", table_of_instance_methods, table_of_static_methods);
...where the instance/static methods are lists of <string, functionpointer> pairs. These register_class calls are wrapped in a nice way that is similar to how LLVM compiler passes register themselves.

When register_class() is called, it adds a new entry to a list of registered classes. Each entry is a structure that looks like this:

code:
struct RTTIEntry
{
    const char* lua_name;
    list_of_stuff instance_method_table;
    list_of_stuff static_method_table;
    std::function<bool(Object*)> check_instance;
};
The first three entries are just the function arguments to register_class(). The last entry is interesting. Background: all the C++ classes available to Lua derive from a class called Object. Not that it's important, but it's similar to the Unity Engine's entity/component model (where you can attach/detach arbitrary Aspects onto an Object at runtime), but I also still have a hierarchy of concrete classes deriving from Object (unlike Unity where everything is an Object, period, I think).

check_instance is a function, which given an Object at runtime, will tell you whether or not that Object is of a class derived from the registered class. The actual lambda assigned to check_instance is:

code:
entry.check_instance = [](Object* o)
{
    return dynamic_cast<CPPClassBeingRegistered*>(o) != nullptr;
});
This list of registered classes, and this curious check_instance function, are used whenever Lua calls C++, and the C++ code wishes to return a handle to a C++ object back to Lua. The returned handle must have the right lua_class_name associated it, so that the Lua code knows which table of instance methods can be called on it. Here's the sequence of events that happens when C++ code wishes to return an instance of a subclass of Object to Lua:

1) The C++ function has an instance of something, but hidden behind a base-class Object* pointer.
2) The list of RTTIEntries is scanned, and each entry's check_instance() is called on the Object* pointer.
3) The first entry that returns true is selected as the Lua class that correspods to the Object*'s actual run-time type.
4) Hooray, that entry's lua_name can now be used to tell Lua what class the returned handle is going to be.

---

What's missing from this system is a way to order the list of RTTIEntries such that if there exist several registered C++ classes that are related to each other, the most-derived classes come first, since they will be encountered first on the linear search in step 3). This is why, during register_class, I'd love to be able to examine the RTTIEntry list and find a smart place to insert the new entry, based on class relationships, without having any instance of anything lying around.

The Laplace Demon
Jul 23, 2009

"Oh dear! Oh dear! Heisenberg is a douche!"

Schmerm posted:

What's missing from this system is a way to order the list of RTTIEntries such that if there exist several registered C++ classes that are related to each other, the most-derived classes come first, since they will be encountered first on the linear search in step 3). This is why, during register_class, I'd love to be able to examine the RTTIEntry list and find a smart place to insert the new entry, based on class relationships, without having any instance of anything lying around.

There's a couple of ways to go about this. Here's a sort of naive approach, where you call your existing is_instance methods on an instance of the new type when you add it to the registry.
C++ code:
struct registry {
    struct entry {
        const char *name;
        bool (*is_instance)(const Object*);
    };
    
    template<typename T>
    void push(const char *name) {
        T t;
        auto it = std::find_if(begin(v), end(v), [&t](const entry& e) { return e.is_instance(std::addressof(t)); });
        v.emplace(it, entry{
            name,
            [](const Object *o) { return dynamic_cast<const T*>(o) != nullptr; }
        });
    }
    
    const entry *find(Object *o) {
        auto it = std::find_if(begin(v), end(v), [o](const entry& e) { return e.is_instance(o); });
        return it == end(v) ? nullptr : std::addressof(*it);
    }
    
    std::vector<entry> v;
};
You can get around constructing an object by (ab)using exceptions.
C++ code:
struct registry {
    struct entry {
        const char *name;
        bool (*is_instance)(const Object*);
        void (*throws)();
        bool (*can_catch_when)(void(*)());
    };
    
    static bool is_base_of(const entry& base, const entry& derived) {
        return base.can_catch_when(derived.throws);
    }
    
    template<typename T>
    void push(const char *name) {
        entry e = {
            name,
            [](const Object *o) { return dynamic_cast<const T*>(o) != nullptr; },
            [] { throw static_cast<T*>(nullptr); },
            [](void (*throws)()) { try { throws(); } catch (T*) { return true; } catch (...) {} return false; }
        };
        auto it = std::find_if(begin(v), end(v), [&e](const entry& base) { return is_base_of(base, e); });
        v.emplace(it, std::move(e));
    }
    
    // ...
};
EDIT: Here's an article about the above RTTI approaches.

The Laplace Demon fucked around with this message at 08:59 on Jan 20, 2015

Schmerm
Sep 1, 2000
College Slice

The Laplace Demon posted:


You can get around constructing an object by (ab)using exceptions.


:monocle: sweet mother of satan! :monocle:

Yep, I think that'll do.

edit: I also didn't know that a standard C-like function pointer can point to a lambda, and thought only std::function could do that
edit2: this will gently caress with the debugger when it's set to break-on-throw, but filtering should fix that

Schmerm fucked around with this message at 19:28 on Jan 20, 2015

pseudorandom name
May 6, 2007

C++ lambdas that don't capture are just function pointers.

(C++ lambdas that do capture are their own unique anonymous struct type with an operator(), which is why you need std::function in the first place.)

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

pseudorandom name posted:

C++ lambdas that don't capture are just function pointers.

No, they're still anonymous (empty) struct types with an operator(); they just also have a conversion operator to function-pointer type.

sd6
Jan 14, 2008

This has all been posted before, and it will all be posted again
I'm a C++ beginner, trying to learn the language and messing around with Qt currently. I just did one of the tutorials where you make a sample program with widgets. It works fine and all, but there's a part of the code I'm not understanding.

textfinder.h:
code:
#ifndef TEXTFINDER_H
#define TEXTFINDER_H

#include <QWidget>

namespace Ui {
class TextFinder;
}

class TextFinder : public QWidget
{
    Q_OBJECT

public:
    explicit TextFinder(QWidget *parent = 0);
    ~TextFinder();

private slots:
    void on_findButton_clicked();

private:
    Ui::TextFinder *ui;
    void loadTextFile();
};

#endif // TEXTFINDER_H
textfinder.cpp:
code:
#include "textfinder.h"
#include "ui_textfinder.h"
#include <QFile>
#include <QTextStream>

TextFinder::TextFinder(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TextFinder)
{
    ui->setupUi(this);
    loadTextFile();
}

TextFinder::~TextFinder()
{
    delete ui;
}
...
If I'm understanding namespaces correctly, the TextFinder class declared in namespace Ui, and the one declared outside the namespace should be two different classes. What I'm not getting is where the member function setupUi() of Ui::TextFinder is coming from, since there's no definition for Ui::TextFinder. Is this some kind of Qt magic that's linking definitions for this stuff, or is there a C++ construct here that I'm not understanding?

Meat Beat Agent
Aug 5, 2007

felonious assault with a sproinging boner
Ui::TextFinder and its setupUi() method are defined in ui_textfinder.h, which is generated at build time from the corresponding .ui file (and then included from textfinder.cpp, whereas in textfinder.h you only need the forward declaration).

sd6
Jan 14, 2008

This has all been posted before, and it will all be posted again

daft punk railroad posted:

Ui::TextFinder and its setupUi() method are defined in ui_textfinder.h, which is generated at build time from the corresponding .ui file (and then included from textfinder.cpp, whereas in textfinder.h you only need the forward declaration).

Ah ok thank you. I figured something like that was going on

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.
I'm looking to drop a real simple webserver into a windows application - it only has to respond to GET requests and will have to serve a page that it generates from some of its own internal state.

Any suggestions for something ready made?

Volguus
Mar 3, 2009

Newf posted:

I'm looking to drop a real simple webserver into a windows application - it only has to respond to GET requests and will have to serve a page that it generates from some of its own internal state.

Any suggestions for something ready made?

Microsoft has made an open source C++ REST SDK that may be able to help: https://casablanca.codeplex.com/

Newf
Feb 14, 2006
I appreciate hacky sack on a much deeper level than you.

Volguus posted:

Microsoft has made an open source C++ REST SDK that may be able to help: https://casablanca.codeplex.com/

A good find, but unfortunately requires a more modern runtime than what I have available.

High Protein
Jul 12, 2009

Newf posted:

I'm looking to drop a real simple webserver into a windows application - it only has to respond to GET requests and will have to serve a page that it generates from some of its own internal state.

Any suggestions for something ready made?

Boost ASIO comes with a web server example that's pretty easy to integrate in other projects.

Joda
Apr 24, 2010

When I'm off, I just like to really let go and have fun, y'know?

Fun Shoe
I have a Cmake/linking question. I set up a project to use GLM, GLFW and SOIL, and while GLFW and GLM come with Cmake files and are compiled with my project, which I assume means the relevant parts of the library are compiled into my executable and it will work when I try to run it on a system that doesn't have these libraries installed. SOIL, however, doesn't come with a Cmake file, and I have to link the library file and include files through my CmakeList. If I took my application and ran it on a system that doesn't have libSOIL.a in the particular path I do, would it then still work? These are the lines where I'm defining/linking SOIL in my CMakeList.txt:

code:
#Find SOIL
set( SOIL_INCLUDE_DIR "${PROJECT_DIR}/soil/src/")
set( SOIL_LIBRARIES "${PROJECT_DIR}/soil/lib/libSOIL.a" )
#Link SOIL
target_link_libraries(glfwtest SOIL ${SOIL_LIBRARIES})
I've never had to set up a major project for a stand-alone application that uses libraries before so I'm still not sure how all this works.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Joda posted:

If I took my application and ran it on a system that doesn't have libSOIL.a in the particular path I do, would it then still work?
Yes, a .a file is a statically linked library. If there's a .so file then you might need to include that. (In Windows, .lib and .dll are broadly the equivalents.) You should never need to distribute a .lib or .a file with a binary.

Edit: vvvv Funny, I did almost say "except silly license agreement cases". :)

roomforthetuna fucked around with this message at 07:36 on Jan 27, 2015

Edison was a dick
Apr 3, 2010

direct current :roboluv: only

roomforthetuna posted:

You should never need to distribute a .lib or .a file with a binary.

I've heard of an edge case to this rule, where you use a LGPL component and need to provide a static binary.
Using shared objects and dynamic linked binaries is the easiest way to satisfy the LGPL, but you can also do it by providing intermediate objects (.o files) and static libraries (.a files), since the LGPL grants the freedom to replace the library with a bugfixed version.

xgalaxy
Jan 27, 2004
i write code
I guess that works if your main program was only a single object file. But that would be pretty stupid if you had a ton of object files. It is simpler to just use dynamic linking.

Adbot
ADBOT LOVES YOU

hooah
Feb 6, 2006
WTF?
It's been a while since I used filestreams, and I'm having a problem I haven't encountered before. I'm trying to create an input filestream from a plain text file, but apparently the failbit for the stream is getting set to true. Here's my code:
C++ code:
#include <iostream>
#include <unordered_map>
#include <fstream>
#include <string>

using std::cerr; using std::cout; using std::endl;
using std::unordered_map;
using std::ifstream;
using std::string;

int main(int argc, char *argv[]){
	if (argc < 2){
		cerr << "Usage: Viterbi datafile" << endl;
		return 1;
	}
	unordered_map<string, string> tagTable;
	cout << "argument 1: " << argv[0] << " 2: " << argv[1] << endl;
	ifstream input(argv[1]);
}
The first file I tried this with looks like this (first 8 lines plus an extra line feed), but I even tried creating a file "test" which just has the word "test", and the failbit gets set on that, too. Any idea what's going on?

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