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
Paniolo
Oct 9, 2007

Heads will roll.

niteice posted:

XInput may also work for you, though it has very specific limitations.

XInput is designed specifically for an Xbox 360 controller so it probably won't work with his racing wheel.

Just use DirectInput.

Adbot
ADBOT LOVES YOU

Null Pointer
May 20, 2004

Oh no!
It might work if it's a 360 wheel. I've never tried, but XInput technically should support them (XINPUT_DEVSUBTYPE_WHEEL.)

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I'm trying to work with the unordered_map in Boost for doing some hashing. I think my problem below is more an issue with templates and how to make them behave. This code is from snippets in unordered_map documentation uses to demonstrate the structure. You'll see that when the unordered_map is typedef'd the code is happy. If I try to spell out the full type, it will not compile.

code:
/* 
 * File:   sandbox.cpp
 * Author: rocko
 *
 * Created on April 3, 2010, 9:43 PM
 */

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <boost/lexical_cast.hpp>
#include <boost/unordered_map.hpp>
#include <boost/foreach.hpp>

using namespace std;

/*
 * 
 */
int main(int argc, char** argv) {
    typedef boost::unordered_map<std::string, int> map;
    map x;
    x["one"] = 1;
    x["two"] = 2;
    x["three"] = 3;

//    BOOST_FOREACH(map::value_type i, x) {         // works
    BOOST_FOREACH(boost::unordered_map< std::string, int>::value_type i, x) {   // BOOST_FOREACH passed 3 arguments, but takes just 2
        std::cout<<i.first<<","<<i.second<<"\n";
    }
    
    assert(x.at("one") == 1);
    assert(x.find("missing") == x.end());
    return (EXIT_SUCCESS);
}

I have some of my own code based off this and I get burnt right there. I will be defining my hash through a typedef to get around it, but for the sake of knowing C++'s pedantic nougat, I wondered if there was a way to spell out the type there w/o it failing to compile.

OddObserver
Apr 3, 2009
Comma confusing a macro, perhaps?

raminasi
Jan 25, 2005

a last drink with no ice
Yeah, BOOST_FOREACH can't handle that.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
Put the type in parens. The preprocessor doesn't recognize < and > as grouping things and so it splits on the comma in your template. Also don't use that god-awful foreach macro (though it's admittedly better than rolling your own).

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
Why do you hate it?

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Mustach posted:

Why do you hate it?

I'll let the source file speak for itself: http://www.boost.org/doc/libs/1_38_0/boost/foreach.hpp

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
That's grosser than I expected.

Jose Cuervo
Aug 25, 2004
I am trying to sort an array of numbers and I am using the sort function in C++. Unfortunately, I cannot think of a way to also come up with an array of sorted indices, eg

If my array is initially [9, 8, 6, 17], the sorted array using sort will be [6, 8, 9, 17], and I would also like to get the array of sorted indices: [3, 2, 1, 4].

Is it possible to get this?

haveblue
Aug 15, 2005



Toilet Rascal
Initialize a second array to [0, 1, 2, 3, 4...] and perform every swap operation on it as well?

emf
Aug 1, 2002



I'm not familiar with sort, and I don't see a man page for it, but if it is like qsort you specify a comparison function for use by the sorting function. Make the array a vector of two elements, with the second element the index. Have your comparison function only use the first element of the vector, but pass the size of the entire vector to the sorting function so that they are swapped together.

Jose Cuervo
Aug 25, 2004

emf posted:

I'm not familiar with sort, and I don't see a man page for it, but if it is like qsort you specify a comparison function for use by the sorting function. Make the array a vector of two elements, with the second element the index. Have your comparison function only use the first element of the vector, but pass the size of the entire vector to the sorting function so that they are swapped together.

I ended up doing something very similar to this. Thank you.

That Turkey Story
Mar 30, 2003

Avenging Dentist posted:

Put the type in parens. The preprocessor doesn't recognize < and > as grouping things and so it splits on the comma in your template. Also don't use that god-awful foreach macro (though it's admittedly better than rolling your own).

Sorry, but BOOST_FOREACH owns, not really much reason to not use it until range-based for. Even with 0x lambdas, BOOST_FOREACH is generally ahead of the game as opposed to std::for_each. Also, simply putting the type in parenthesis will not work. The way the parenthesis trick usually works with other macros is that inside the macro, the type parameter is referred to as something along the lines of function_traits< void your_type_param_name >::arg1_type. It can be made to account for [basic] cases of void by just having a metafunction that yields void when passed a function type with no args. The downsides of this are that it means you always have to pass your type in parenthesis regardless of whether or not is has commas, there are some cases it doesn't handle, at least not as intended (function types, array types, typedefed void, etc), and it internally may need to use typename cases where it's a dependent name.

If you're using a compiler that supports the 0x use of auto (GCC works fine), just use auto with BOOST_FOREACH instead of specifying the type, unless you need to be portable to compilers that are not able to handle it yet. More portably, just use a typedef as described in the docs.

Zaxxon
Feb 14, 2004

Wir Tanzen Mekanik
ok this is likely a simple question but after a while of googling around I can't find a satisfactory example.

I am creating a series of instrument objects which have parameters that need to be accessed and changed by a uniform system. So each object needs to have a set of parameters and each parameter needs a description, but the descriptions need to be unique and constant.

So I want each instrument base class to define some constant parameter descriptions, however I get compiler errors whenever I try and declare a constant in the class interface. It looks a bit like this

code:

struct parameter_description
{
  int size;
  int min;
  int max

  parameter_description(int size, int min, int max); //this does the obvious
};

class instrument : instrument_base
{
  //blah blah blah
  protected:
  static const parameter_description PD_one(1,0x0,0xF);
  static const parameter_description PD_two(2,0x0,0xFF);

};
I suppose I could just make those descriptions static and only access them through constant references. but I'd rather just have those descriptions be constant and have each parameter just point to them.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
Construct the objects outside of the class.

Zaxxon
Feb 14, 2004

Wir Tanzen Mekanik

Avenging Dentist posted:

Construct the objects outside of the class.

is that really the best practice?

I was doing that originally but I thought it made more sense to have the descriptions linked to the class. Especially since a bunch of different classes are going to have parameters with similar names like amp or frequency that may have different bounds.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Zaxxon posted:

is that really the best practice?

It is not so much a "best practice" as "required by the standard". Note that you can keep them as class members.

code:
class parameter_description {
  ...
  static const parameter_description PD_one;
  ...
};

// This has to go in a unique translation unit, i.e. not in a header.
const parameter_description parameter_description::PD_one(1,0x0,0xF);

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Got another couple of questions. I think I know the answers to both, but I want to be sure.

1) When using an ofstream, is there any way to write binary values using the stream operators, or do I have to use write() with a size? I suspect the latter, and though wrapping around that is no big deal, it seems strange. I woulda thought the ios::binary flag would change the behavior of the stream operators.

2) When templating a function, is it possible to make a particular attempted instantiation raise a compile-time error as below? (I suspect the answer is, again, "no, make it fail at runtime with an assert in a specialization or something")

code:
template <typename T>
void foo(T bar)
{
 // blah
}

int main()
{
  int a = 5;
  double b = 3;
  char[3] c = "baz";

  foo(a); // ok
  foo(b); // ok
  foo(c); // can this be made a compile-time error?
}
Thanks!

Zaxxon
Feb 14, 2004

Wir Tanzen Mekanik

rjmccall posted:

It is not so much a "best practice" as "required by the standard". Note that you can keep them as class members.

code:
class parameter_description {
  ...
  static const parameter_description PD_one;
  ...
};

// This has to go in a unique translation unit, i.e. not in a header.
const parameter_description parameter_description::PD_one(1,0x0,0xF);

ah! Thanks, thats what he meant! I feel dumb because I was trying to do something like this at first

code:
class Instrument{
  ...
  static const parameter_description PD_one;
  ...
};

// This has to go in a unique translation unit, i.e. not in a header.
const Instrument::PD_one(1,0x0,0xF);
and was getting errors, so I thought I was doing something not allowed and moved them into the header. Then what I thought avenging dentist meant is that I had to declare them as outside the class definition.

Vanadium
Jan 8, 2005

Ledneh posted:

Got another couple of questions. I think I know the answers to both, but I want to be sure.

1) When using an ofstream, is there any way to write binary values using the stream operators, or do I have to use write() with a size? I suspect the latter, and though wrapping around that is no big deal, it seems strange. I woulda thought the ios::binary flag would change the behavior of the stream operators.

iostreams are for formatted text output. The binary flag refers to opening a file in binary mode, that is not converting lineendings or whatever funny mechanics your OS imposes on text files.

quote:

2) When templating a function, is it possible to make a particular attempted instantiation raise a compile-time error as below? (I suspect the answer is, again, "no, make it fail at runtime with an assert in a specialization or something")

This works for me:

code:
#include <boost/type_traits.hpp>
#include <boost/utility.hpp>

template <typename T>
typename boost::disable_if<typename boost::is_same<T, char*>::type>::type
foo(T bar)
{
  // blah
}

int main() {
  int a = 5;
  double b = 3;
  char c[] = "baz";

  foo(a); // ok
  foo(b); // ok
  foo(c); // can this be made a compile-time error?
}

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Vanadium posted:

iostreams are for formatted text output. The binary flag refers to opening a file in binary mode, that is not converting lineendings or whatever funny mechanics your OS imposes on text files.

Oh, okay. Should I be using something other than fstream for binary file writing/reading then, or is .write() and .read the best I'm going to get?

And thanks for the template trick :)

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

Vanadium posted:

This works for me:

code:
#include <boost/type_traits.hpp>
#include <boost/utility.hpp>

template <typename T>
typename boost::disable_if<typename boost::is_same<T, char*>::type>::type
foo(T bar)
{
  // blah
}

int main() {
  int a = 5;
  double b = 3;
  char c[] = "baz";

  foo(a); // ok
  foo(b); // ok
  foo(c); // can this be made a compile-time error?
}

:colbert: http://codepad.org/HKgcutnR

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Avenging Dentist posted:

:colbert: http://codepad.org/HKgcutnR

I'm so terrible at this profession. :doh:

floWenoL
Oct 23, 2002

Avenging Dentist posted:

:colbert: http://codepad.org/HKgcutnR

That's a link-time error. :colbert:

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh

floWenoL posted:

That's a link-time error. :colbert:

I like linking the errors are more fun.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
code:
class Forbidden { ~Forbidden(); };

template <class T> void foo(T);
Forbidden foo(char *);

void test() {
  char a[] = "help";
  foo(a);
}
The amusing thing about this is that I checked it with clang and found a bug.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"
The correct answer is to use C++0x to add your own meaningful, smug diagnostic:

code:
#include <type_traits>

template <typename T>
void foo(T value)
{
    static_assert(!std::is_same<T, char*>::value,
        "don't call this with a char* you rear end in a top hat");

    // Do something
}

int main()
{
    int a = 5;
    double b = 3;
    char c[] = "baz";

    foo(a); // ok
    foo(b); // ok
    foo(c); // can this be made a compile-time error?
      
    return 0;
}
code:
$ g++-4.5 -std=c++0x test.cpp
test.cpp: In function ‘void foo(T) [with T = char*]’:
test.cpp:20:10:   instantiated from here
test.cpp:6:5: error: static assertion failed: "don\'t call this with a char* you rear end in a top hat"
EDIT: or this!

code:
#include <type_traits>

template <typename T>
void foo(T value)
{
    // Do something
}

void foo(char*) = delete;

Flobbster fucked around with this message at 03:47 on Apr 7, 2010

Contero
Mar 28, 2004

This isn't a question, but I think this is probably the best place for it.

I've gotten really sick of YACC, ANTLR and Spirit so I decided to roll my own parser generator that's contained entirely in C++ like Spirit is. The idea is that at every assignment for a rule all of the parsed results get handed off to your function where you can process them and eventually return any type you want. In this case it's an int. I think the end result is simple, clean, easy to set up and gives you a lot of freedom to construct whatever you want.

code:
enum { LP, RP, PLUS, MULT, NUM };

const char *program = "(4 + 6) * 7 + 3";

int doAdd(std::vector<RuleResult> results)
{
   int ret = results[0].getVal<int>();

   for (unsigned i = 2; i < results.size(); i += 2)
      ret += results[i].getVal<int>();

   return ret;
}

...

int main ()
{
   Lexer lexer;

   lexer.type(LP, "\\(");
   lexer.type(RP, "\\)");
   lexer.type(PLUS, "\\+");
   lexer.type(MULT, "\\*");
   lexer.type(NUM, "[0-9]+");
   lexer.ignore("\\s");

   Rule<int> addExpr(doAdd), multExpr(doMult), valExpr(doVal);

   addExpr = multExpr + *( TR(PLUS) + multExpr );

   multExpr = valExpr + *( TR(MULT) + valExpr );

   valExpr = TR(LP) + addExpr + TR(RP)
           | TR(NUM);

   addExpr.check();
   multExpr.check();
   valExpr.check();

   int result = addExpr.start(lexer.lex(program));

   cout << "result: " << result << endl;

   return 0;
}
The lexer uses boost::regex. I made the lexer and parser separate so you can easily use just the lexer if you want or modify the token stream returned by lex() to do interesting things like removing nested block comments: /* /*... */ */.

It's a little rough around the edges of course. I've just implemented throw away (!) and optional (~) rules, but haven't tested them out yet.

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


I'm (not) proud of this template exclusion solution. http://codepad.org/W2H3T5Ea

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
You can reduce that entire second part to is_pointer. Also you forgot about volatile variables. http://codepad.org/MvuXbKPK

That Turkey Story
Mar 30, 2003

Avenging Dentist posted:

You can reduce that entire second part to is_pointer. Also you forgot about volatile variables. http://codepad.org/MvuXbKPK

You're all over-complicating things :smug:

http://codepad.org/lg4Cp1ab

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Well this post series was certainly a learning experience. Thanks for the education and correction :)

Ciaphas fucked around with this message at 00:33 on Apr 8, 2010

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
I wish type_traits had a base type trait to strip out all arrays refs, pointers, and cv-qualifiers.

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


That's what I was looking for at first when I started reading about the enable/disable_if constructs, yeah. :(


Actually, on that last codepad, is the is_pointer clause even necessary? It looks like the star in the second is_convertible parameter covers that, making the is_pointer redundant, unless I'm missing something important here (read: I'm missing something).

That Turkey Story
Mar 30, 2003

Ledneh posted:

That's what I was looking for at first when I started reading about the enable/disable_if constructs, yeah. :(


Actually, on that last codepad, is the is_pointer clause even necessary? It looks like the star in the second is_convertible parameter covers that, making the is_pointer redundant, unless I'm missing something important here (read: I'm missing something).
You are missing the fact that types can have an overloaded conversion operator to a [qualified] char pointer. Without the is_pointer check, it would incorrectly disallow people from using the template with such a type.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
TTS explained it but here's the code: http://codepad.org/sMZ1yblu

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


Slowly I continue to learn things. Thanks you two :)

CaptainMcArrr
Oct 4, 2003
PACWANKER HAS HORSE COCK
Hi guys, I hope you can help with what (I think) is a relatively stupid C question but for some reason I can't quite wrap my head around it. The classes I've done have sort of glossed over headers so they're still a bit confusing.

Basically I've got a program with multiple (3) c files. I've got a structure that's used across all of them. Where do I define it and how do I import it?

I tried creating a types.h file and putting it in there, but then the other header files threw a hissy fit because, I guess, they couldn't see it?

I hope I'm explaining myself okay - can anyone help?

Adbot
ADBOT LOVES YOU

UraniumAnchor
May 21, 2006

Not a walrus.
That's pretty much exactly what you want to do (put the structure declaration in a .h file), so you might have to be more specific about what is going wrong.

If another header refers to your struct you need to include the struct header beforehand.

Edit:

code:
foo.h
-----

struct foo {
 int x;
};

bar.h
-----

#include "foo.h"

struct bar {
 struct foo f;
};
Or, optionally, in any file that includes bar.h you need to include foo.h in that file before, such as:

code:
main.c
-----

#include "foo.h"
#include "bar.h"
Hopefully that makes it more clear.

UraniumAnchor fucked around with this message at 07:52 on Apr 9, 2010

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