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
Doc Block
Apr 15, 2003
Fun Shoe

PRADA SLUT posted:

I noticed that after. It still outputs correctly.

Which is purely accidental.

Adbot
ADBOT LOVES YOU

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

PRADA SLUT posted:

I noticed that after. It still outputs correctly.
Even if you clip a wire and live, you're not an EOD tech.

Star War Sex Parrot
Oct 2, 2003

PRADA SLUT posted:

I noticed that after. It still outputs correctly.
brb firing up my VM with Valgrind

JawKnee
Mar 24, 2007





You'll take the ride to leave this town along that yellow line

Scrapez posted:

I'm only comparing the last random number to the current one, meaning that I end up with two of the four numbers being the same occasionally.

Should I be reading each random number into its own variable like randOne, randTwo, randThree, randFour? How would I do that?

Others have noted that you should use an array to store your generated numbers, but essentially yes: for this particular problem (as you've stated it) you will need to have some way to explicitly check each new random number you generate against all the previous numbers you've generated, which would mean storing all the generated numbers, and then checking against them.

JawKnee fucked around with this message at 10:23 on Feb 1, 2016

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...

PRADA SLUT posted:

I noticed that after. It still outputs correctly.

Just #define NUMS_TO_OUTPUT 4 and use that in both the for loops and also the array size. That way you can't ever mismatch them.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

MutantBlue posted:

If the initial value is an int then all the intermediate values are int and the final return value is an int. It's just int = int * int64_t at every step and it's your fault if the operation overflows or truncates. Look at the example implementations on cppreference.com.

To elaborate on this: template argument deduction works by trying to make the template's parameter types match the corresponding argument types more-or-less exactly. This is done independently for all the arguments, and if a different type is deduced in a different argument, that's an error (which causes the template to be ignored as a candidate, which may or may not actually cause compilation to fail). Also, this is all done without considering the body of the template, so it has no idea that the template feeds that initial value into the function argument and returns the result and thus the best deduction would be the fixpoint; nor is there any way you could figure out that fixpoint in general in C++ anyway.

So, basically, if a function template has a parameter that's declared directly to have type T (or T && or const T & or something like that), and you pass it an int, you can be sure that either T is going to be inferred to be int or deduction is going to fail. Specifically, it's never going to deduce some type that int happens to be convertible to. This is why you'll sometimes see libraries that intentionally "break" deduction for a parameter by writing it as something like std::enable_if<true, T>::type: template argument deduction is required to treat this as a non-deducible context, so it'll ignore it; that way, if T is deducible in some other way, and the argument type happens to be convertible to that, everything will just work. This is useful when the correct binding for T is unambiguously deducible from some other argument (e.g. if the caller's supposed to pass in a T&), or if the template author wants to force the caller to write the type manually (e.g. std::forward).

rjmccall fucked around with this message at 11:44 on Feb 1, 2016

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.

Shy posted:

Do JetBrains have any plans to make CLion work with MS toolchain? Anyone knows?
Not in the near future, but according to their issue tracker they will keep mind open.

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?

MutantBlue posted:

Since it's such a small range of numbers you might consider just shuffling the numbers 1..25 and then taking the first 4.

C++ code:
#include <algorithm>
#include <iostream>
#include <numeric>
#include <random>
#include <vector>
 
int main()
{
	std::mt19937 rng(std::random_device{}());
 
	std::vector<int> numbers(25);
	std::iota(begin(numbers), end(numbers), 1); // [1,25]
	std::shuffle(begin(numbers), end(numbers), rng); // randomize
	numbers.resize(4); // truncate
 
	for (int value : numbers) {
		std::cout << value << '\n';
	}
}

This is the best way IMO.

Scrapez
Feb 27, 2004

Is there a way to achieve the result without using an array? I have worked with arrays a bit elsewhere so I can see that would be a viable method, however, this is a programming assignment for chapter 3 of this book and we don't cover arrays until chapter 5. My assumption is that they want the answer without using an array.

The only way I can think to do it is to make it really inefficient where I generate a random number and stuff it into a variable and then do the same a second time, then compare the values, then stuff a random number in a third variable and compare to the first two and again for the fourth. But if one of those variables should match one of the previous, I'd have to generate a new number.

Could I make the random number generator a function and then right an if statement that says if ran2 != ran, proceed else go to the random number generator function again. And then once they are not equal, move on to another if statement that says if ran3 != ran2 && ran3 != ran1 proceed else go to random function again.

It seems like that might work, though inefficient. Am I missing something there?

nielsm
Jun 1, 2009



If you're not supposed to use arrays, then you can't really solve the problem in a "good" (general) manner.

Then just make your four variables for storing the numbers in and write plain, linear code to fill one random number into each. Then after filling each variable, add something to check that it's not a repeat value, you will need a loop for that.


... actually, now I think about it, you can do a (partially) generalized version with four plain variables, but it's not entirely straight forward. You'll have to use them as a stack, for that.

Scrapez
Feb 27, 2004

Though it isn't elegant, I think this works without using arrays. I've run it many times and it seems to generate the four random numbers without any of them matching.

code:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main()
{
	// Declare variables
	srand(time(0));
	int randNumOne, randNumTwo, randNumThree, randNumFour;
	int randNumGen();

    
    randNumOne=randNumGen();
    
    randNumTwo=randNumGen();
    while (randNumTwo == randNumOne)
    randNumTwo=randNumGen();
    
    randNumThree=randNumGen();
    while (randNumThree == randNumTwo || randNumThree == randNumOne)
    randNumThree=randNumGen();
    
    randNumFour=randNumGen();
    while (randNumFour == randNumThree || randNumFour == randNumTwo || randNumFour == randNumOne)
    randNumFour=randNumGen();

    cout << randNumOne << " " << randNumTwo << " " << randNumThree << " " << randNumFour;
	return 0;
}
	
int randNumGen()

{
    int randNum=0;
	randNum = (rand() % 25 + 1);
	return randNum;
}

Scrapez fucked around with this message at 17:20 on Feb 1, 2016

nielsm
Jun 1, 2009



Yep, that's the straight-forward way to do it. It's not very neat, as you can probably tell.

My idea for a more general one:
C++ code:
int main()
{
  int a, b, c, d, i;
  a=b=c=d=0;

  for (i = 0; i < 4; i++)
  {
    // make room at position a
    d=c;
    c=b;
    b=a;
    // new value
    a = (rand()%25) + 1;
    while (a==b || a==c || a==d)
      a = (rand()%25) + 1;
  }
  printf("Values: %d %d %d %d\n", a, b, c, d);
}
By the way, put your code into [code] tags, makes it look nicer :)

Scrapez
Feb 27, 2004

Thanks, I added the code tags. Yours is actually more efficient with the loop so I think I'll incorporate that. Thanks for the help.

PRADA SLUT
Mar 14, 2006

Inexperienced,
heartless,
but even so

Doc Block posted:

Which is purely accidental.

Don't hate on my ingenuous, memory-conserving programming techniques.

The_Franz
Aug 8, 2003

Sagacity posted:

Not in the near future, but according to their issue tracker they will keep mind open.

That doesn't mean much coming from them. They've been saying the same thing about integrating libclang as an alternative to their homegrown parser (which still doesn't support some newer C++ features and often flags valid code as wrong) and they still haven't done it yet.

Hyvok
Mar 30, 2010
Are there any useful tricks for implementing or at least easing of making "bidirectional" algorithms/functions? For example I am doing the Matasano crypto challenges and I did a hex-encoded ASCII -> base64 conversion function and now I'd need to make the same but the other way around... Feels stupid/error prone to just duplicate the same stuff the other way around. Can't think of any simple way to make it simpler/more generic either. I'm sure you can do something clever with some template/functional magic but...

Malcolm XML
Aug 8, 2009

I always knew it would end like this.

Hyvok posted:

Are there any useful tricks for implementing or at least easing of making "bidirectional" algorithms/functions? For example I am doing the Matasano crypto challenges and I did a hex-encoded ASCII -> base64 conversion function and now I'd need to make the same but the other way around... Feels stupid/error prone to just duplicate the same stuff the other way around. Can't think of any simple way to make it simpler/more generic either. I'm sure you can do something clever with some template/functional magic but...

i haven't seen anything though you could take some inspiration from automatic differentiation libraries that preserve the operation tree

Malcolm XML fucked around with this message at 19:40 on Feb 2, 2016

nielsm
Jun 1, 2009



Hyvok posted:

Are there any useful tricks for implementing or at least easing of making "bidirectional" algorithms/functions? For example I am doing the Matasano crypto challenges and I did a hex-encoded ASCII -> base64 conversion function and now I'd need to make the same but the other way around... Feels stupid/error prone to just duplicate the same stuff the other way around. Can't think of any simple way to make it simpler/more generic either. I'm sure you can do something clever with some template/functional magic but...

Use two simple arrays of each encoding's alphabet to generate finite state automata, then have a generic execution engine for those.
Or otherwise generate simple, complete mappings from input sequences to output sequences.

sarehu
Apr 20, 2007

(call/cc call/cc)

Hyvok posted:

Are there any useful tricks for implementing or at least easing of making "bidirectional" algorithms/functions? For example I am doing the Matasano crypto challenges and I did a hex-encoded ASCII -> base64 conversion function and now I'd need to make the same but the other way around... Feels stupid/error prone to just duplicate the same stuff the other way around. Can't think of any simple way to make it simpler/more generic either. I'm sure you can do something clever with some template/functional magic but...

In my experience trying to be clever about this sort of repeat-yourself-once-but-backwards avoidance is generally a terrible idea, and the most useful trick is to write the logic one way and then write the opposite. In your case it should be easy to make a convincing test suite.

And the source of this opinion was something which would seem a lot simpler to do "once", pairs of serialization/deserialization functions.

Hyvok
Mar 30, 2010

sarehu posted:

In my experience trying to be clever about this sort of repeat-yourself-once-but-backwards avoidance is generally a terrible idea, and the most useful trick is to write the logic one way and then write the opposite. In your case it should be easy to make a convincing test suite.

And the source of this opinion was something which would seem a lot simpler to do "once", pairs of serialization/deserialization functions.

Yeah just generally wondering, my example is very short/simple to do by hand anyway. More about if I'm missing some technique to increase code re-use.

Aramis
Sep 22, 2009



It's "kinda" feasible with expression templates, but that's a rabbit hole I wouldn't recommend going down.

For an example, you can look at boost::spirit::qi and boost::spirit::karma where that sort of symmetric logic is applied in theory.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
For conversion specifically, it's often better to write all your conversions to/from a suitable intermediate format (and do all your other conversions by composing them together). That way, if you have n different formats you're talking about, you just need 2n conversion functions instead of n2.

Sex Bumbo
Aug 14, 2004
The answer is no, there's no trivial way to do that. There's infinite non-trivial ways to do it though.

Olly the Otter
Jul 22, 2007
Why can't I do the following?
code:
template <typename PropertyTree>
void foo(const PropertyTree &tree)
{
	tree.get_value<int>();
}
I get "error: expected primary-expression before ‘int’" using g++ 4.9.2. (The template function definition alone is enough to give me an error, even without invoking it.)

It works if I provide a non-template function:

code:
#include <boost/property_tree/ptree.hpp>
void foo(const boost::property_tree::iptree &tree)
{
	tree.get_value<int>();
}
Is there some way I can call template methods, when the actual class is itself a template parameter (so that my function can also be used with other property_tree types)?

netcat
Apr 29, 2008
I'm on the phone so this might not be the exact syntax but iirc you have to call it like this:
code:
tree. template get_value<int>()

Olly the Otter
Jul 22, 2007
That worked, thanks!

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today
Clang tends to give more helpful errors in cases like this, so you might consider trying it next time you're deep in template shenanigans and nothing makes sense.

Rottbott
Jul 27, 2006
DMC

netcat posted:

I'm on the phone so this might not be the exact syntax but iirc you have to call it like this:
code:
tree. template get_value<int>()
:aaa: Every time I think I've finally learned everything about this language...!

Tarion
Dec 1, 2014

Rottbott posted:

:aaa: Every time I think I've finally learned everything about this language...!

Have you read the standard's description of what the ?: operator does? Especially when given user defined types?

Volguus
Mar 3, 2009
I have a question about a little piece of code that I'm writing:
I have a base_controller class with a bunch of controllers that extend base_controller and override a bunch of methods in base. When a request comes in I dispatch the request to one of the appropriate controllers that I have registered for that particular request (I have a std::unordered_map<std::string,std::unique_ptr<base_controller>> that keeps track of which is which).
The dispatch methods are all virtual overridden from the base_controller.
Now, the dispatch methods ... are all the same, the difference only being the method that will get called in the corresponding controller. In order to write less code, I came up with this :

C++ code:
template <typename Callable>
bool api_controller::call_sub_controller(Callable&& cb,const Request& request, Response& response)
{
  auto identifier = get_controller_identifier(request); 
  auto controller = sub_controllers.find(identifier);
  bool found = (controller != sub_controllers.end());
  if( found )
  {
    auto new_req = request;
    new_req.uri = get_controller_uri(request);
    ((controller->second.get())->*cb)(new_req,response); //here I call the overridden method of whatever controller has been registered for that identifier
  }
  return found;
}

//and I call it like this
void api_controller::method1(const Request& request, Response& response)
{
  if(!call_sub_controller(&base_controller::method1,request,response)) // here I dispatch to the appropriate sub controller, and if I cannot find one, call the base class
  {
    base_controller::method1(request,response);    
  }
}

This works. Took me a bit to find out the correct syntax, but it works.
But now I have method2 which has 3 parameters, but otherwise is the same as method1: api_controller::method2(const Request& request, Response& response, const std::vector< char >& body).
Is there a way that I can modify call_sub_controller to work for both?
I tried with variadic templates, but the call to the subcontroller ... went nowhere. That is, the program didn't crash, but it was like the call was not getting made, even though it reached ((controller->second.get())->*cb) line.

Here's what I tried:
C++ code:
template <typename Callable,typename Req,typename...Arguments>
bool api_controller::call_sub_controller(Callable&& cb,const Req& request, Arguments....params)
{
//code as  before...
    ((controller->second.get())->*cb)(new_req,params);
//....
}
//and I call it as before
Question 1: Is there a way to accomplish my goal (not have 2 methods with identical bodies, except for 1 little line) and not use a macro?
Question 2: From the above code, all of the dispatch methods look like this:
C++ code:
void api_controller::method1(const Request& request, Response& response)
{
  if(!call_sub_controller(&base_controller::method1,request,response)) // here I dispatch to the appropriate sub controller, and if I cannot find one, call the base class
  {
    base_controller::method1(request,response);
  }
}
Can the code in the template function be modified so that the base class method1 is called if found == false? Something like this produces a stack-overflow, because is of course calling the method1 is api_controller instead of the class:
C++ code:
template <typename Callable>
void api_controller::call_sub_controller(Callable&& cb,const Request& request, Response& response)
{
  auto ident = get_controller_identifier(request);
  auto controller = sub_controllers.find(ident);
  bool found = (controller != sub_controllers.end());
  if( found )
  {
    auto new_req = request;
    new_req.uri = get_controller_uri(request);
    ((controller->second.get())->*cb)(new_req,response);
  }
  else
  {
	(this->*cb)(request,response);
  }
}
Thank you.

Edit: I am using Fedora 23 with gcc (GCC) 5.3.1 20151207 (Red Hat 5.3.1-2) with -std=c++14

Volguus fucked around with this message at 14:45 on Feb 9, 2016

eth0.n
Jun 1, 2012

Volguus posted:

Here's what I tried:

There are a few issues with this, although none are clear causes for what you've observed:
  • Some syntax errors, which should be causing compile errors: 4 dots instead of 3 in the function signature, and no dots after params in the function pointer call
  • Functions don't appear to be inline, which all template functions should be (although they might be declared as such in the class body, but that's not the usual way of doing it). If they're not inline, there might be undiagnosed ODR violations.
  • Not using perfect forwarding; not a matter of correctness here, but might as well do it.

Here's a version with those things addressed:

C++ code:
template <typename Callable,typename Req,typename...Arguments>
inline bool api_controller::call_sub_controller(Callable&& cb,const Req& request, Arguments&&...params)
{
//code as  before...
    ((controller->second.get())->*cb)(new_req, std::forward<Arguments>(params)...);
//....
}
//and I call it as before
I would not expect this to solve your problem, but it's possible. Have you tried using a debugger and stepping through the function pointer call?

quote:

Can the code in the template function be modified so that the base class method1 is called if found == false? Something like this produces a stack-overflow, because is of course calling the method1 is api_controller instead of the class:

No, not with your current structure. A pointer-to-virtual-method will always call the most-derived version of that method, which is the one you're in. You could put your actual logic in a protected non-virtual base_controller::method1_impl, and call it from your virtual base_controller::method1, then pass &base_controller::method1_impl as an additional parameter to call_sub_controller.

Volguus
Mar 3, 2009

eth0.n posted:

Possible solution ....

Thank you.
That's what I get for typing things from memory on a topic that I never used before, such as variadic templates. My code was compilable of course, just not working. Been reading in the last few days Meyer's Effective Modern C++ (11 and 14), and unfortunately I still cannot understand universal references and perfect forwarding. Either Scott is not explaining well or i'm just thick. Or both.
It "looks" to be a relatively easy topic but, ugh ... I'll have to study harder I guess.

Anyway, thanks for the pointers. Haven't thought about ODR violations, I'll fix and try again asap.

Edit: This indeed solved my problem. Thank you.

Volguus fucked around with this message at 00:57 on Feb 11, 2016

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

Rottbott posted:

:aaa: Every time I think I've finally learned everything about this language...!
https://www.youtube.com/watch?v=rNNnPrMHsAA

JawKnee
Mar 24, 2007





You'll take the ride to leave this town along that yellow line
I'm using a small library, tinyfiledialogs, in something I'm making. I'm only making use of the Open File dialogs across systems, but I've run into a problem that seems to have something to do with either GetOpenFileName or the involved GETOPENFILENAME struct, but only appears to be cropping up on 64 bit versions of Windows; the problem is this: calling for a second Open File dialog box causes the program to crash without any errors being thrown (or at least none I've been able to catch).

I decided to try and just write my own small Open File functions to see if I could figure it out, but I'm still not sure what's causing the problem. This:

code:
#include <stdio.h>
#include <windows.h>

void openD(){
	
char Filestring[1024] = "\0";
OPENFILENAME ofn={0};

ofn.lStructSize = sizeof(OPENFILENAME);
ofn.lpstrFile = Filestring;
ofn.nMaxFile = 1024;
ofn.Flags = OFN_EXPLORER | OFN_ALLOWMULTISELECT;

GetOpenFileName(&ofn);
}

int main()
{
openD();
openD();
}
Crashes shortly after the second Dialog window is opened every time on my 64 bit machine. I suppose I should take this as encouragement to use the Common Item Dialog instead?

csammis
Aug 26, 2003

Mental Institution
Is the first call to GetOpenFileName returning TRUE or FALSE? If it's FALSE, what's the CommDlgExtendedError?

If you're running this in Debug from Visual Studio is there anything printed in the output console which might indicate an exception being thrown or an abnormal program termination error code?

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!
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!

b0lt
Apr 29, 2005

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!

auto will have no overhead, it'll derive the anonymous type of the lambda.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

b0lt posted:

auto will have no overhead, it'll derive the anonymous type of the lambda.

I don't know about "no" overhead. It'll probably compile to a type with sizeof(poop) == 1 and will hopefully never actually generate loads or stores to that byte, which is as little overhead as C++ allows, though.

+lambdas aren't really intended to "avoid std::function overhead", they're intended for compatibility with C callbacks. If you're in a pure-C++ API and you care about avoid std::function, you do so by using templates parameterized by the type of a functor, which lets lambdas get as close as possible to having zero storage, while still enabling the use of closures.

JawKnee
Mar 24, 2007





You'll take the ride to leave this town along that yellow line

csammis posted:

Is the first call to GetOpenFileName returning TRUE or FALSE? If it's FALSE, what's the CommDlgExtendedError?

If you're running this in Debug from Visual Studio is there anything printed in the output console which might indicate an exception being thrown or an abnormal program termination error code?

The first call returns True, during the second call the program crashes prior to returning a value.

I don't normally program in Windows so I may be using the VS express debugger incorrectly, but attaching it to the process got me the following exceptions when the application attempted the second call:

First the popup:
code:
Unhandled exception at 0x759C36DC (shell32.dll) in ofd_64.exe: 0xC0000005: Access violation reading location 0x70017AD8.
Followed by this in output:
code:
First-chance exception at 0x759C36DC (shell32.dll) in ofd_64.exe: 0xC0000005: Access violation reading location 0x70017AD8.
Unhandled exception at 0x759C36DC (shell32.dll) in ofd_64.exe: 0xC0000005: Access violation reading location 0x70017AD8.
The program '[5904] ofd_64.exe' has exited with code 0 (0x0).

Adbot
ADBOT LOVES YOU

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).

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