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
fritz
Jul 26, 2003

Soricidus posted:

I, ::paul:: of-the-family ::atreides::, the flesh and blood man

Muad'Dab on em.

Adbot
ADBOT LOVES YOU

Ranzear
Jul 25, 2013

Munkeymon posted:

Sure, but what's the "law" where you can't tell if someone is kidding or actually just that stupid/crazy/far up their own rear end? I feel like that's at play here.

Poe's Law

Nothing better describes the present decade.

TheresaJayne
Jul 1, 2011

Ranzear posted:

Poe's Law

Nothing better describes the present decade.

What about the Classic Laws

Cole's Law - Thinly Sliced Cabbage

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Ranzear posted:

Poe's Law

Nothing better describes the present decade.

Indeed, one day scholars will recognize the eras BCE, CE and ARS, the latter meaning "After (Humanity Descended Into) Recursive Self-Parody

Soricidus
Oct 21, 2010
freedom-hating statist shill

Munkeymon posted:

Indeed, one day scholars will recognize the eras BCE, CE and ARS, the latter meaning "After (Humanity Descended Into) Recursive Self-Parody

anno ricardo stallmani, or in the vulgar tongue, the year of gnu/linux on the desktop

fritz
Jul 26, 2003

Am I the horror for thinking that maybe
code:
  template<int i,typename std::enable_if<i==0>::type* = nullptr>
  void f(int a, double b) const{
	/// stuff
  }
  template<int i,typename std::enable_if<i==1>::type* = nullptr>
  void f(int a, double b) const{
    // stuff
  }
  template<int i,typename std::enable_if<i==2>::type* = nullptr>
  void f(int a, double b) const{
     // stuff
   }
is a regrettable idea?

ultrafilter
Aug 23, 2007

It's okay if you have any questions.


If your goal is to have your name cursed extra hard, then it's a great idea.

Volguus
Mar 3, 2009

fritz posted:

Am I the horror for thinking that maybe
code:
  template<int i,typename std::enable_if<i==0>::type* = nullptr>
  void f(int a, double b) const{
	/// stuff
  }
  template<int i,typename std::enable_if<i==1>::type* = nullptr>
  void f(int a, double b) const{
    // stuff
  }
  template<int i,typename std::enable_if<i==2>::type* = nullptr>
  void f(int a, double b) const{
     // stuff
   }
is a regrettable idea?

Does this code means that calling f<0>(int,double) is different than calling f<1>(int,double)? If yes ... what on earth got into you? I'm not a people person (to put it mildly) but I would never do this to my worst enemy.

fritz
Jul 26, 2003

Volguus posted:

Does this code means that calling f<0>(int,double) is different than calling f<1>(int,double)? If yes ... what on earth got into you? I'm not a people person (to put it mildly) but I would never do this to my worst enemy.

It absolutely does, and I want to make it clear that this is NOT my code.

fritz
Jul 26, 2003

It was decided that we're going to use a thing (also full of template abuse) that depends on this package, and one of its dependencies is templated to such an extent that visual studio refuses to compile it as-is.

Volte
Oct 4, 2004

woosh woosh
You don't need that SFINAE poo poo though:

code:
#include <cstdio>

template <int N>
void hello(int a) {
    printf("%d\n", N * a);
}

template <>
void hello<2>(int a) {
    printf("whoops\n");
}

int main() {
    hello<1>(2);
    hello<2>(2);
    hello<3>(2);
    return 0;
}
code:
2
whoops
6
Doing it for no reason is obviously bad but there could be legitimate reasons to specialize on certain parameters (i.e. to use different SIMD instructions based on vector length or something).

SardonicTyrant
Feb 26, 2016

BTICH IM A NEWT
熱くなれ夢みた明日を
必ずいつかつかまえる
走り出せ振り向くことなく
&



My friend told me that they had to shut down his job's database utility because they found out that the username/password page was just a placeholder; it only used hardcoded values. And that they only found out because they were getting a lot of traffic from China.

There is no screaming externally gif big enough.

Dylan16807
May 12, 2010

Volguus posted:

Does this code means that calling f<0>(int,double) is different than calling f<1>(int,double)? If yes ... what on earth got into you? I'm not a people person (to put it mildly) but I would never do this to my worst enemy.
Is there a reason you would expect them to do the same thing? Sure, it's bad form to stuff multiple behaviors into one function name, and to use magic numbers instead of an enum. I wouldn't call it horror-free. But why is it a problem for the code to do a different thing when you give it a different parameter?

Dylan16807 fucked around with this message at 01:03 on Dec 18, 2018

xtal
Jan 9, 2011

by Fluffdaddy

Dylan16807 posted:

Is there a reason you would expect them to do the same thing? Sure, it's bad form to stuff multiple behaviors into one function name, and to use magic numbers instead of an enum. I wouldn't call it horror-free. But why is it a problem for the code to do a different thing when you give it a different parameter?

You answered your own question, except the answer was before the question.

xtal fucked around with this message at 01:16 on Dec 18, 2018

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
It really is not hard to come up with examples of functions which reasonably should do completely unrelated things depending on the value of a parameter. An obvious one: an event loop which switches on the event type.

Volguus
Mar 3, 2009

Dylan16807 posted:

Is there a reason you would expect them to do the same thing? Sure, it's bad form to stuff multiple behaviors into one function name, and to use magic numbers instead of an enum. I wouldn't call it horror-free. But why is it a problem for the code to do a different thing when you give it a different parameter?

The name. If i see 2 functions with the same name but a different signature (and this would qualify, even though it gets generated into multiple functions), i would expect them to do the same thing or at least have the same effect even if they do it differently. However, it is true that I do not know for a fact what kind of "stuff" the functions posted did, and it may be that they just did the same thing.

Plorkyeran posted:

It really is not hard to come up with examples of functions which reasonably should do completely unrelated things depending on the value of a parameter. An obvious one: an event loop which switches on the event type.

I have a hard time thinking of anything reasonable. The event loop that switches on the event type can be called a dispatch. It does one thing: it dispatches the event to other functions that are going to handle it. I'd find it extremely horror for the function to do different things depending n the even type, such as: dispatch the even to a function if you're event type X, open a file and write character Y into it if you're type B. Creating function "handleEventB" that opens the file and writes the character would be perfectly acceptable. Having it done in the dispatch function, no.

Dylan16807
May 12, 2010

Volguus posted:

I have a hard time thinking of anything reasonable. The event loop that switches on the event type can be called a dispatch. It does one thing: it dispatches the event to other functions that are going to handle it. I'd find it extremely horror for the function to do different things depending n the even type, such as: dispatch the even to a function if you're event type X, open a file and write character Y into it if you're type B. Creating function "handleEventB" that opens the file and writes the character would be perfectly acceptable. Having it done in the dispatch function, no.
That template code is equivalent to a dispatch function that calls "handleEvent0", "handleEvent1", or "handleEvent2" depending on the first parameter.

The dispatch itself is so simple that you make the compiler generate it for you. Nothing is done "in" it.

Dylan16807
May 12, 2010

xtal posted:

You answered your own question, except the answer was before the question.
Let me rephrase.

As long as it's basically the same process, there is nothing weird about having a parameter change the behavior of a function.

This parameter is badly named but otherwise there doesn't seem to be anything inherently wrong with the pattern.

It would be weird to expect f(true, 5, 7.8) and f(false, 5, 7.8) to do the same thing, right? Moving the parameter into the signature doesn't really change that.

QuarkJets
Sep 8, 2008

Dylan16807 posted:

Let me rephrase.

As long as it's basically the same process, there is nothing weird about having a parameter change the behavior of a function.

This parameter is badly named but otherwise there doesn't seem to be anything inherently wrong with the pattern.

It would be weird to expect f(true, 5, 7.8) and f(false, 5, 7.8) to do the same thing, right? Moving the parameter into the signature doesn't really change that.

It's fine to slightly change a function's behavior depending on the input. But that's not what the example was showing; the example was showing 3 completely separate functions stuffed into one, the exact behavior that you described as bad form. Why do this? Why not have 3 separate functions, each with a good name describing what it does, instead of one vaguely-named function containing 3 unrelated behaviors that are chosen by setting a parameter?

Dylan16807
May 12, 2010

QuarkJets posted:

the example was showing 3 completely separate functions stuffed into one
It just says "//stuff" though? We don't know how similar the three function bodies are. All we know is they're not exactly the same.


QuarkJets posted:

Why not have 3 separate functions, each with a good name describing what it does, instead of one vaguely-named function containing 3 unrelated behaviors that are chosen by setting a parameter?
In that specific case, agreed.

On the other hand, if it's Flunge_Sprocket and Flunge_Widget vs. Flunge<Sprocket> and Flunge<Widget>, either one could be better depending on context.

QuarkJets
Sep 8, 2008

Dylan16807 posted:

It just says "//stuff" though? We don't know how similar the three function bodies are. All we know is they're not exactly the same.

Why would their similarities or dissimilarities matter in this case? As-written, the example shows that nothing is shared between the three functional segments. Having the same block of code appear in all 3 segments makes the situation worse, not better

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
It's just pattern matching on a function argument, which C++ happens to not have very nice syntax for. There's no fundamental difference between

code:
template<int>
void foo() { printf("else\n"); }

template<>
void foo<0>() { printf("zero\n"); }

template<>
void foo<1>() { printf("one\n"); }
and

code:
void foo(int n) {
    switch (n) {
        case 0: printf("zero\n"); break;
        case 1: printf("one\n"); break;
        default: printf("else\n"); break;
    }
}
other than that language limitations sometimes force you to pass the argument as a template argument. Obviously you should not have a function that switches on an int and then does some completely unrelated things for no reason, and similarly you should obviously not have a pile of completely unrelated functions named with magic numbers. I don't see any reason to assume that the snipped out portion contained some horror greater than totally gratuitous SFINAE.

Plorkyeran fucked around with this message at 08:32 on Dec 18, 2018

QuarkJets
Sep 8, 2008

Plorkyeran posted:

Obviously you should not have a function that switches on an int and then does some completely unrelated things for no reason, and similarly you should obviously not have a pile of completely unrelated functions named with magic numbers. I don't see any reason to assume that the snipped out portion contained some horror greater than totally gratuitous SFINAE.

Yeah, that's fundamentally all that we're talking about : using templates or switch statements or if/else statements for the magic parameter is moot, the actual problem is having a bunch of different (or vaguely similar while not sharing any code) functions captured in one for no real benefit

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
What makes you so confident that there is no reason for the code to be dispatching to different functions based on the value of a compile-time function?

EssOEss
Oct 23, 2006
128-bit approved
My heart tells me this is exactly how the C++ standardization committee works.

fritz
Jul 26, 2003

Dylan16807 posted:

It just says "//stuff" though? We don't know how similar the three function bodies are. All we know is they're not exactly the same.

In that specific case, agreed.

On the other hand, if it's Flunge_Sprocket and Flunge_Widget vs. Flunge<Sprocket> and Flunge<Widget>, either one could be better depending on context.

I'm not at the computer with the code on it, but I do remember that this code was for computing jacobians, <0> and <2> were doing different things, and <1> was a nop.

ChickenWing
Jul 22, 2010

:v:

dear thread


today...I am the coding horror





may god have mercy on my newly synchronized code

QuarkJets
Sep 8, 2008

Plorkyeran posted:

What makes you so confident that there is no reason for the code to be dispatching to different functions based on the value of a compile-time function?

The problem isn't the dispatching, the problem is having 3 different functions in 1. So in my opinion this would be fine:

code:
void alter_data(int &x, int param) {
    if (param == 0) {
        foo(x);
    } else if (param == 1) {
        bar(x);
    } else {
        butt(x);
    }
}
It would be better to just call whatever function you need instead of passing in a parameter, but there are cases where the behavior above makes sense. That's not being disputed

Dylan16807
May 12, 2010

QuarkJets posted:

The problem isn't the dispatching, the problem is having 3 different functions in 1. So in my opinion this would be fine:

code:
void alter_data(int &x, int param) {
    if (param == 0) {
        foo(x);
    } else if (param == 1) {
        bar(x);
    } else {
        butt(x);
    }
}
It would be better to just call whatever function you need instead of passing in a parameter, but there are cases where the behavior above makes sense. That's not being disputed
I'm just not understanding how this:
code:
alter_data<Foo>(p);
alter_data<Bar>(p);
alter_data<Butt>(p);
is any worse than this:
code:
alter_data(Foo, p);
alter_data(Bar, p);
alter_data(Butt, p);
It's three functions either way. Treat alter_data<Foo> as the full name of the function.

This is assuming you use an enum instead of a magic value, because that's a separate and easily solved issue.

And this way you know for sure that passing in Foo won't call butts because someone goofed up the dispatch. The compiler handles the dispatch for you.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

QuarkJets posted:

The problem isn't the dispatching, the problem is having 3 different functions in 1. So in my opinion this would be fine:

code:
void alter_data(int &x, int param) {
    if (param == 0) {
        foo(x);
    } else if (param == 1) {
        bar(x);
    } else {
        butt(x);
    }
}
It would be better to just call whatever function you need instead of passing in a parameter, but there are cases where the behavior above makes sense. That's not being disputed

Your opinion is stupid.

Not really much more to say than that. This whole “three function in one” thing is a really dumb way to think about template specialization.

Soricidus
Oct 21, 2010
freedom-hating statist shill

Dylan16807 posted:

I'm just not understanding how this:
code:
alter_data<Foo>(p);
alter_data<Bar>(p);
alter_data<Butt>(p);
is any worse than this:
code:
alter_data(Foo, p);
alter_data(Bar, p);
alter_data(Butt, p);
it's because one of them is dumb and bad and weird and non-obvious, and the other is a standard way of handling function calls in computer languages. just because something is a legal way to write something doesn't mean it's a good idea. conventions exist for a reason and violating them is bad unless you get a meaningful benefit, which in this case you don't.

Dylan16807 posted:

And this way you know for sure that passing in Foo won't call butts because someone goofed up the dispatch. The compiler handles the dispatch for you.
and how does the compiler help you "know for sure" that someone didn't goof up the template specializations instead of the dispatch?

in both cases you're counting on the function you're calling being implemented correctly. you don't achieve any extra safety by doing it the weird and unintuitive way, you just confuse people and make them curse the day you learned to type.

Volte
Oct 4, 2004

woosh woosh

Soricidus posted:

it's because one of them is dumb and bad and weird and non-obvious, and the other is a standard way of handling function calls in computer languages. just because something is a legal way to write something doesn't mean it's a good idea. conventions exist for a reason and violating them is bad unless you get a meaningful benefit, which in this case you don't.

and how does the compiler help you "know for sure" that someone didn't goof up the template specializations instead of the dispatch?

in both cases you're counting on the function you're calling being implemented correctly. you don't achieve any extra safety by doing it the weird and unintuitive way, you just confuse people and make them curse the day you learned to type.
The "weird and unintuitive way" is moving a conditional to compile-time, which is good. It means that this is a path where the underlying conditional would and should always go the same way and if it doesn't, it's an error. Why insist that the conditional should linger uselessly? Depending on the construction of alter_data and the interface that Foo would have to implement, the statically resolved way could potentially be inlined as well, which is impossible if you have any sort of indirection associated with that interface.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Obviously writing things in an awkward way to have it be evaluated at compile time is a bad idea if you don’t need it to be evaluated at compile time.

If you do need it to be evaluated at compile time then you suck it up and write the awkward code while complaining about how you wish you could use c++17 and just use constexpr if.

QuarkJets
Sep 8, 2008

Plorkyeran posted:

Your opinion is stupid.

Not really much more to say than that. This whole “three function in one” thing is a really dumb way to think about template specialization.

This post just makes it seem like you didn't understand what I wrote. Maybe that's my fault. The template aspect of the question is weird but isn't actually an issue IMO, I don't know how to make that any clearer

QuarkJets
Sep 8, 2008

Dylan16807 posted:

I'm just not understanding how this:
code:
alter_data<Foo>(p);
alter_data<Bar>(p);
alter_data<Butt>(p);
is any worse than this:
code:
alter_data(Foo, p);
alter_data(Bar, p);
alter_data(Butt, p);
It's three functions either way. Treat alter_data<Foo> as the full name of the function.

They're basically the same, yes. The former is unconventional and there's no real benefit to using it, but I think it's fine.

There are situations where it makes sense to use templates, and"well I want to use a check on the template value instead of a switch or if/else statement" doesn't seem like one of them, but it's not really a horror

QuarkJets fucked around with this message at 07:02 on Dec 19, 2018

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
Yesterday I created a new unit test project and added it to the overnight build. When it comes to run the tests, Microsoft's test runner can't find the test methods because of some tool versioning issue with how the assembly is built and how the build action for running the test is configured. What does it do? It prints this message in the log: "Warning: No test is available in [name of assembly].dll." And it doesn't fail the build. I wouldn't have even known that these tests don't actually run if I hadn't looked through the log for confirmation.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Hammerite posted:

Yesterday I created a new unit test project and added it to the overnight build. When it comes to run the tests, Microsoft's test runner can't find the test methods because of some tool versioning issue with how the assembly is built and how the build action for running the test is configured. What does it do? It prints this message in the log: "Warning: No test is available in [name of assembly].dll." And it doesn't fail the build. I wouldn't have even known that these tests don't actually run if I hadn't looked through the log for confirmation.

Oh yeah, that's actually one of my biggest issues with the mstest runner - it really loving sucks at finding the unit tests. I've had cases where they worked in the gated check-in but not on my local build and vice versa and it's all configuration related.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Bruegels Fuckbooks posted:

Oh yeah, that's actually one of my biggest issues with the mstest runner - it really loving sucks at finding the unit tests. I've had cases where they worked in the gated check-in but not on my local build and vice versa and it's all configuration related.

My issue is that it doesn't fail the build for this. I could forgive everything else

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Hammerite posted:

My issue is that it doesn't fail the build for this. I could forgive everything else

i think it not failing the build is a consequence of the design of the test runner/framework though - like, it can't know to fail the build because the tests didn't run because it didn't know that there were tests, and the toolchain errors seem to be runtime, not compile time.

maybe there's a reason they don't do this, but I would think that emitting meta-information about which tests are in the dll (like an xml file or something if you build a test project) on build and using that as the basis of test discovery would be smarter than trying to figure out which tests exist in the dll from type annotations. the discovery of tests via searching through every test dll looking for annotated methods the way mstest is doing it seems slow and dependent on the dll being loadable, and i've seen it either not work or just be really loving slow enough times that I just won't use ms test if I don't have to.

Adbot
ADBOT LOVES YOU

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Bruegels Fuckbooks posted:

i think it not failing the build is a consequence of the design of the test runner/framework though - like, it can't know to fail the build because the tests didn't run because it didn't know that there were tests, and the toolchain errors seem to be runtime, not compile time.

Then it's a poo poo design.

Whatever the reason, if I tell it to run tests in a DLL and it doesn't find any tests, it's an error and I should be told about it. If I told it to run tests then that means that I think there are tests. Either I'm wrong and I should be told so (and I should go fix my build script), or something is wrong and the tests can't be found, in which case they aren't going to get run and I need to be alerted to that - it should be treated as equivalent to a failing test.

The way it's set up at the moment, I can add a unit test project to my build script and go away happily thinking that if any of my tests fail then my build will fail. Whereas in fact that's not going to happen, I haven't got the checking safety net I thought I had. I've been given a false sense of security because Microsoft hosed up.

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