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
WHERE MY HAT IS AT
Jan 7, 2011
I know, and I don't really want to post those as it gets into "having other people do your homework" territory. I appreciate the suggestions though, thanks :)
Edit: I figured it out! I took all the re declared private members out of my child class, and used the methods that I already had to just use the private variables in my parent class. It seems super obvious now and I feel dumb for not seeing it sooner. But still, thanks again for the help, everyone!

WHERE MY HAT IS AT fucked around with this message at 22:10 on Mar 21, 2013

Adbot
ADBOT LOVES YOU

dragon enthusiast
Jan 1, 2010
Looking for suggestions on how to implement this in the least lovely way possible.
code:
#include <cstdio>

 class AbstractClass {
    public:
        struct Structure{};
        virtual void function(Structure *in) = 0;
};

 class DerivedClass: public AbstractClass {
    public:
        struct Structure: public AbstractClass::Structure {
            int member;
        };

        void function(AbstractClass::Structure *in) {
            printf("It works %d\n", ((DerivedClass::Structure *) in) -> member);
        };
};

int main() {

    AbstractClass *a = new DerivedClass;

    DerivedClass::Structure *b;
    b -> member = 5;

    a -> function(b);

    return 0;
}
Basically I want an interface that defines a structure that belongs specifically to each of the subclasses that derive the interface and a function that does stuff with that structure.

The above is the closest I've gotten to what I want, but I'd really prefer not to have to cast the input every time plus it kind of breaks polymorphism.

seiken
Feb 7, 2005

hah ha ha
What would you intend to happen if you passed the wrong kind of derived class Structure to the function, and if the answer is "it wouldn't work", then what's the point of the function being virtual at all? If the answer is "it wouldn't compile" you might want templates rather than inheritance

seiken fucked around with this message at 23:07 on Mar 21, 2013

dragon enthusiast
Jan 1, 2010

seiken posted:

What would you intend to happen if you passed the wrong kind of derived class Structure to the function, and if the answer is "it wouldn't work", then what's the point of the function being virtual at all? If the answer is "it wouldn't compile" you might want templates rather than inheritance
Like I said that was the closest approximation to a working solution I could find, and if there were a way to ensure type safety then I'd be all for it.

I want polymorphism so I can do stuff like
code:
AbstractClass *a;
AbstractClass::Structure *b;

if(flag == 0) {
  a = new DerivedClass1;
  b = new DerivedClass1::Structure;
}
else if(flag == 1) {
  a = new DerivedClass2;
  b = new DerivedClass2::Structure;
}
else etc.

a -> function(b);

The actual contents of the interface(s) are freely modifiable, I just want to enforce the ability to tie a certain struct definition to a certain class as close to compile time as possible.

dragon enthusiast fucked around with this message at 23:32 on Mar 21, 2013

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Four options:

1. You can use templates, where instead of creating A and B and calling a virtual method on A, you template all the code between the point you create A and B and the point at which you start passing B to A's methods.

2. You can use encapsulation, where B holds a properly-typed A or vice-versa.

3. You can switch to a language with a crazily rich type system that can express this directly. I don't know of any that isn't actually a theorem prover. What you want falls within the general category of existential typing.

4. You can do what you're currently doing it and just live with the fact that no, it's not going to be statically type-safe.

seiken
Feb 7, 2005

hah ha ha
I kind of think this is an X/Y problem and you should explain what you're actually doing and why you want this because the use case you gave is sort of odd.

That Turkey Story
Mar 30, 2003

rjmccall posted:

Four options:

1. You can use templates, where instead of creating A and B and calling a virtual method on A, you template all the code between the point you create A and B and the point at which you start passing B to A's methods.

2. You can use encapsulation, where B holds a properly-typed A or vice-versa.

3. You can switch to a language with a crazily rich type system that can express this directly. I don't know of any that isn't actually a theorem prover. What you want falls within the general category of existential typing.

4. You can do what you're currently doing it and just live with the fact that no, it's not going to be statically type-safe.

Without knowing more about the problem, I agree especially with option 1. What it sounds like you are representing is a single concept modeled by multiple different types, and that concept also has an associated type that must model a different concept. This is a perfect case for templates, pending of course that compile-time polymorphic behavior is all you need. If you want an example of this in actual code, it's done in the C++ standard library with containers and iterators. std::vector, std::list, std::deque, etc. are models of the sequence concept, and that concept includes an associated iterator type that models an iterator concept. These containers each have "insert" and "erase" functions that take an instance of the container's corresponding iterator type. Similarly, there are generic algorithms in the standard library that work with any of those iterator types. Further, attempting to use a list's iterator with a vector's "erase" will [in any reasonable implementation] not compile. However, because they all model the same concept, you can still write algorithms that are templates that will work with any of your types. These containers can also be used with the container adaptors such as std::queue. There are no virtual functions or even inheritance directly required to make these containers. All polymorphic behavior is strictly compile-time.

It's easy to default to using inheritance and virtual functions whenever you need polymorphic behavior, and for statically typed languages that don't have something that provides analogous behavior to templates there's often not much more that you can do than that, but in C++ I find that it's usually more useful to default to using templates unless you actually need the run-time behavior of virtual functions. The other downside is obviously that templates generally require you to have a bit of a deeper understanding of the language and the error messages are a bit more difficult to read.

Edit: To make it more clear, I commented up your code a bit

code:
#include <cstdio>

// Note: This class doesn't exist at all in the template approach
 class AbstractClass { // This is analogous to a container concept
    public:
        struct Structure{}; // This is analogous to an associated iterator type
        virtual void function(Structure *in) = 0; // This is analogous to a container's erase
};

 // This is analogous to a model of the concept (i.e. std::vector is a model of container)
 class DerivedClass: public AbstractClass { // Inheritance wouldn't be necessary
    public:
        struct Structure: public AbstractClass::Structure { // This would just be the container's iterator type
            int member;
        };

        void function(AbstractClass::Structure *in) { // This would just be the container's erase function
            printf("It works %d\n", ((DerivedClass::Structure *) in) -> member);
        };
};

That Turkey Story fucked around with this message at 01:26 on Mar 22, 2013

dragon enthusiast
Jan 1, 2010
What I want to do is create a class that takes input data, does calculations and poo poo on it, and returns a pointer to the processed output data. The struct in this case is metadata associated with the input data.

I wanted the polymorphism aspect because there's a lot of possible stuff I could do with the input data, and it all requires different metadata (and different output structs). But as far as the end user is concered all he needs to do is call process(struct *metaData, inputType *inputData).

Delta-Wye
Sep 29, 2005
I have been idly working on a problem I've had off and on for years and I'm still not sure the easiest way to implement it. The problem relates to parsing streams of data (I do embedded electronics, so say RS232 serial characters, one after another) looking for strings. For example, you have a AT-compatible modem and you are communicating with it. On such a system, you get a hardware generated interrupt every time you receive a character. The interrupt calls a function which can read the character out of a hardware register and do something with it. I think a nice approach to the problem could be an acceptor state machine.

The theory is straight forward, but the implementation is killing me. I am trying to use as much standard C as I can, as it is the most widely accepted language for the platforms I work on. I happen to love function pointers, so I made a function for each state that accepts the next character as an argument, and sets the function pointer to the appropriate follow up state for the next character.

The concept is easy enough, and it seems like a good fit for my use case. Often times I have plenty of flash (code space) but am limited in both memory and processing time. There are other caveats to keep in mind, but it's mostly corner-case type stuff on particular platforms (hardware stacks!!!! :argh:). The problem I have is generating the necessary code. Take this simple state machine, looking for the strings 'cat', 'hat' and 'hood' in a incoming character stream.


I defined a state machine for holding all of my current information:
code:
struct state_machine {
	int isValid;
	int index;
	void (*current)(char);
};
Each state is a simple function consiting of a switch statement. If a character is recognized, it sets the current function pointer to the correct next function. If not, it is set to the initial state. Here is an example state, the initial state:
code:
void state0(char input) {
	// initial
	switch (input) {
		case 'c':
			sm->current = &state1;
			break;
		case 'h':
			sm->current = &state3;
			break;
		default:
			sm->current = &state0;
			break;
	}
}
The function 'state3' in this case would switch if it gets an 'a' or an 'o' or reset to state0 otherwise. Note that there needs to be two 'a' and 't' states. The pointer-function approach requires two separate states as there is no attempt to save a history. This means that each string adds quite a few possible states, unless they are mostly the same at the beginning (thank you AT spec). Nevertheless, it can be chore to work up the hundreds (!) of states that may be necessary to fully describe a complicated text-based grammar. What I would like to do is automate the process of state building, at compile time. I've considered writing a perl or python script to generate all of the needed state functions based on a given dictionary (totally doable) but its making me think that I have hosed up my approach in the first place; is there a better way of implementing this? It seems like a simple problem, but I have not seen any particularly good approaches. In my case, costly string searches and the like are off the table due to hardware constraints.

seiken
Feb 7, 2005

hah ha ha

just a butt posted:

What I want to do is create a class that takes input data, does calculations and poo poo on it, and returns a pointer to the processed output data. The struct in this case is metadata associated with the input data.

I wanted the polymorphism aspect because there's a lot of possible stuff I could do with the input data, and it all requires different metadata (and different output structs). But as far as the end user is concered all he needs to do is call process(struct *metaData, inputType *inputData).

If rjmccall or turkey story disagree then go with whatever they say but I think you're over-engineering this (or still not giving the full story). From what you've said you just want some functions with arbitrary parameter types and semantics to share the same name, which is handled quite well by overloading:

C++ code:
struct Structure {};
struct OtherStructure {
  int member;
};

struct OutputStructure {};
struct OtherOutputStructure {
  int member;
};

OutputStructure* process(Structure* metaData, InputType* inputData);
OtherOutputStructure* process(OtherStructure* metaData, InputType* inputData);
Turkey Story's post is a great post but since you haven't given any correspondences among the structure types or the various implementations of the process function, I don't see any reason why virtual functions or templates would be useful

seiken fucked around with this message at 01:16 on Mar 23, 2013

nielsm
Jun 1, 2009



Delta-Wye posted:

I have been idly working on a problem I've had off and on for years and I'm still not sure the easiest way to implement it. The problem relates to parsing streams of data (I do embedded electronics, so say RS232 serial characters, one after another) looking for strings.

As you suggest, you should be generating this code. Commonly, this is known as a parser generator. (Or in your case it looks like just a basic lexer.) You could either use a pre-existing one (e.g. flex, which is a lexer generator) or write your own if existing ones don't work under your constraints.

Also, I would really suggest using a table-based approach. Most likely, your function-pointer based approach will use more memory in the end since you need separate machine code for every single state, and each state will need to store multiple full pointers to following states, while with a table-based approach you should be able to get away with storing only the characters you are looking for and an index into your table for the next state. A table-based approach should also be more cache-friendly, I think.

seiken
Feb 7, 2005

hah ha ha

quote:

I have been idly working on a problem I've had off and on

What you're describing is essentially a very constrained kind of regular expression engine (with only alternation and concatenation) which should be pretty easy to implement if you look up how.

Delta-Wye
Sep 29, 2005

nielsm posted:

As you suggest, you should be generating this code. Commonly, this is known as a parser generator. (Or in your case it looks like just a basic lexer.) You could either use a pre-existing one (e.g. flex, which is a lexer generator) or write your own if existing ones don't work under your constraints.

Also, I would really suggest using a table-based approach. Most likely, your function-pointer based approach will use more memory in the end since you need separate machine code for every single state, and each state will need to store multiple full pointers to following states, while with a table-based approach you should be able to get away with storing only the characters you are looking for and an index into your table for the next state. A table-based approach should also be more cache-friendly, I think.

Cache, heh.


seiken posted:

What you're describing is essentially a very constrained kind of regular expression engine (with only alternation and concatenation) which should be pretty easy to implement if you look up how.

Both great. While my friends doing pure CS learned about tokenization et al, I was learning emag. Any chance you'd be willing to gift me a few links or book titles that I can peruse?

EDIT: Sorry, that reads a bit more snarky than I intended. Part of my difficulty is I simply don't know the proper terminology for some of this stuff as its outside of my experience. I understand what you mean by "a very constrained kind of regular expression engine (with only alternation and concatenation)", and I would like to look up how, I'm just not sure what the hell to call such a thing. I guess I should get something like this http://www.amazon.com/dp/0521607655/ and read the chapters on lexical analysis and parsing.

Delta-Wye fucked around with this message at 01:39 on Mar 23, 2013

seiken
Feb 7, 2005

hah ha ha
I apologise for not actually being able to recommend a resource that I have personally used, but with some quick googling I found these online lectures on the theory that look pretty decent and this stuff about actual implementation might be useful although some of them are more focused on the speed stuff which you don't need if you're pre-generating this. And you don't need the star operator or any nesting so you don't need half the code also

A compilation book, while certainly interesting and valuable, may well skip the foundation regex/finite automata stuff that you really want and go straight to lexing, which is probably more than you need for this problem. edit: I know the dragon book definitely has the automata and regex stuff, but you'd only need like the first chapter

Edit again: to clarify, all you need to do to solve your specific problem is precompute a DFA table from e.g. "cat|hat|hood" and use that to process the stream at runtime.

seiken fucked around with this message at 02:22 on Mar 23, 2013

Max Facetime
Apr 18, 2009

Delta-Wye posted:

The function 'state3' in this case would switch if it gets an 'a' or an 'o' or reset to state0 otherwise.

This part can be simplified further. If your state machine knows to handle 'did not match' state changes differently then it can try matching the same input in all states that are an option in this place until one of them matches or the state machine goes to state0.

In your example state3 would expect 'a' or something else. If 'a' is not given as input state3 can call state4 straightaway and give the same input it got. Then in state4 if the input is not 'o' it resets to state0.

jiggerypokery
Feb 1, 2012

...But I could hardly wait six months with a red hot jape like that under me belt.

If I return a struct as a const, will its member variables effectively be const too?

nielsm
Jun 1, 2009



jiggerypokery posted:

If I return a struct as a const, will its member variables effectively be const too?

Uh, I'm not sure that makes sense. A return value can't be const in itself, since it's (formally) a copy of the value returned. You can return a pointer or reference to a const thing, though. Of course that requires the thing to be allocated somewhere else.

seiken
Feb 7, 2005

hah ha ha
You can, but it doesn't make a lot of sense because you'd be returning a copy anyway. But if you return it as a const reference then yes.

jiggerypokery
Feb 1, 2012

...But I could hardly wait six months with a red hot jape like that under me belt.

The structure in question is part of a private array. I was going to overload [] to allow access to its members but I don't want them to be editable.

So you are saying as long as i don't return a reference or pointer I am in the clear yeah?

nielsm
Jun 1, 2009



C++ code:
struct Foo {
  int x, y;
};
class Bar {
  Foo stuff[100];
public:
  Bar get_copy(size_t i) const { return stuff[i]; }
  Bar const & get_constref(size_t i) const { return stuff[i]; }
  Bar & get_plainref(size_t i) { return stuff[i]; }
};
Bar::get_copy() will get a copy of the Foo, also causing any copy constructor for Foo to be run.
Bar::get_constref() will return a reference into the private array, but the reference is to a const value so you can't modify the contents of the private array.
Bar::get_plainref() will return a non-const reference, so that reference will allow you to modify the contents of the private array.

The first two functions are also marked const, since they can't modify the Bar object itself. The first returns a copy, so it's safe. The second returns a const ref, so it's also safe.
Any of those functions could of course also be implemented as operator[] instead, I just named them differently for the purpose of this example.

That Turkey Story
Mar 30, 2003

nielsm posted:

Uh, I'm not sure that makes sense. A return value can't be const in itself, since it's (formally) a copy of the value returned. You can return a pointer or reference to a const thing, though. Of course that requires the thing to be allocated somewhere else.

You can have a const return type and it is different from a non-const return type. One is a const r-value while the other is a non-const r-value. That said, it's not particularly useful to have a const return type.

jiggerypokery posted:

The structure in question is part of a private array. I was going to overload [] to allow access to its members but I don't want them to be editable.

So you are saying as long as i don't return a reference or pointer I am in the clear yeah?

Yeah. Again, you are returning a copy. Modifying the data will just be modifying a copy of the data that was stored privately.

Boz0r
Sep 7, 2006
The Rocketship in action.
Is there some way to find out which functions take the longest to run so I know what optimizations are most important?

EDIT: Also, find out which variables are unused. I'm using VS2010.

Boz0r fucked around with this message at 14:03 on Mar 25, 2013

nielsm
Jun 1, 2009



Boz0r posted:

Is there some way to find out which functions take the longest to run so I know what optimizations are most important?

It's called profiling.
The higher-tier editions of Visual Studio have a built-in tool for it, or you can look for third-party tools.

cliffy
Apr 12, 2002

Boz0r posted:

EDIT: Also, find out which variables are unused. I'm using VS2010.

I think the VS compiler will emit warnings about unused variables by default. If it isn't look up what the flag is to emit all warnings, in gcc-land it's -Wall.

nielsm
Jun 1, 2009



cliffy posted:

I think the VS compiler will emit warnings about unused variables by default. If it isn't look up what the flag is to emit all warnings, in gcc-land it's -Wall.

Only for local variables. If you have fields in classes/structs or globals you don't know whether are in use, try commenting them out and see if you get errors compiling :)

schnarf
Jun 1, 2002
I WIN.

nielsm posted:

Only for local variables. If you have fields in classes/structs or globals you don't know whether are in use, try commenting them out and see if you get errors compiling :)

If you can run it, Clang also has -Wunused-private-field which is pretty neat!

Boz0r
Sep 7, 2006
The Rocketship in action.
I'll see if I can't get a fancy version of VS from the university, thanks.

Rothon
Jan 4, 2012

Boz0r posted:

I'll see if I can't get a fancy version of VS from the university, thanks.

You should be able to get a copy of VS 2012 Professional from DreamSpark.

Goreld
May 8, 2002

"Identity Crisis" MurdererWild Guess Bizarro #1Bizarro"Me am first one I suspect!"

nielsm posted:

It's called profiling.
The higher-tier editions of Visual Studio have a built-in tool for it, or you can look for third-party tools.

Another way to profile your code if you don't have the cash for something nice like Zoom (and aren't running Linux so can't use kcachegrind) is to put scoped timers in your code.

They're simple to implement - merely create a class that records the time when it constructs, then logs/prints its lifetime when it destructs. Then just throw it into the first line of a method/function and voila - it'll automatically log the total time spent in that function.

It's called a scoped timer because it records the time from instantiation until it goes out of scope (ie. when you exit the function the destructor's called).

If you have access to Zoom then I'd recommend that, though - Zoom is great!

Goreld fucked around with this message at 22:16 on Mar 26, 2013

Vanadium
Jan 8, 2005

Why is noexcept better than throw() again, if throwing an exception past it still isn't undefined behavior?

edit: I'm asking for a friend

That Turkey Story
Mar 30, 2003

Vanadium posted:

Why is noexcept better than throw() again, if throwing an exception past it still isn't undefined behavior?

edit: I'm asking for a friend

The big pluses are the ability to directly specify whether or not a given function can throw an exception based on a compile-time constant (often based on whether or not another expression can throw), and that a noexcept does not need to unwind the stack. The latter makes it possible for callers of noexcept functions to be more optimal than callers of throw() functions in a compliant compiler.

Acer Pilot
Feb 17, 2007
put the 'the' in therapist

:dukedog:

Can someone explain what I'm doing wrong? I'm trying to reuse threads by having them just sit in an idle state until they get a signal.

I also want my main() to wait for the threads to go back into their idle state before continuing.

NUM_THREADS is 4, job_lock is a pthread_mutex_t, can_work and jobs_done are pthread_cond_t, jobs_completed is a bool and jobs_complete is an int.

C++ code:
void* Work::job(void* id)
{
    int idx = (long)id;

    while(1)
    {
        pthread_mutex_lock(&job_lock);

        while(!jobs_complete)
        {
            // wait for main to broadcast
            pthread_cond_wait(&can_work, &job_lock);
            pthread_mutex_unlock(&job_lock);

            // work here

            pthread_mutex_lock(&job_lock);
            ++jobs_completed;

            if(jobs_completed == NUM_THREADS)
            {
                jobs_complete = true;
                pthread_cond_signal(&jobs_done);
                pthread_mutex_unlock(&job_lock);
            }
            pthread_mutex_unlock(&job_lock);
        }

        pthread_mutex_unlock(&job_lock);
    }

    return NULL;
}
Right now, I'm doing this right now by calling pthread_cond_broadcast() and then pthread_cond_wait() right after it but this seems to deadlock. Can anyone explain how I should be doing this or where I went wrong?

C++ code:
// work

jobs_completed = false;
jobs_complete = 0;
pthread_mutex_lock(&job_lock);
pthread_cond_broadcast(&can_work);
pthread_cond_wait(&jobs_complete);
pthread_mutex_unlock(&job_lock);

// work that depends on jobs_complete
e: Also, am I using too many unlocks() than required?

Acer Pilot fucked around with this message at 08:19 on Mar 28, 2013

shrughes
Oct 11, 2008

(call/cc call/cc)

KNITS MY FEEDS posted:

Can someone explain what I'm doing wrong? I'm trying to reuse threads by having them just sit in an idle state until they get a signal.

I don't really feel like explaining how to do condition variables right and all the insane and wrong things you're doing, so I'm going to say this.

Make a socketpair for each job thread and use that to talk to your threads.

greatZebu
Aug 29, 2004

KNITS MY FEEDS posted:

Can someone explain what I'm doing wrong? I'm trying to reuse threads by having them just sit in an idle state until they get a signal.

You should either use an existing threadpool implementation like http://threadpool.sourceforge.net/ or resign yourself to spending a lot of time learning and debugging.

Acer Pilot
Feb 17, 2007
put the 'the' in therapist

:dukedog:

Agh, thanks guys. I'll look into socketpairs or maybe use a thread pool instead.

pseudorandom name
May 6, 2007

Alternately, just start by figuring out how a blocking queue works, move on to the other stuff once you've mastered that.

Vanadium
Jan 8, 2005

That Turkey Story posted:

The big pluses are the ability to directly specify whether or not a given function can throw an exception based on a compile-time constant (often based on whether or not another expression can throw), and that a noexcept does not need to unwind the stack. The latter makes it possible for callers of noexcept functions to be more optimal than callers of throw() functions in a compliant compiler.

This seems really complicated to get right, I think I am going to jump ship into the -fno-rtti -fno-exceptions camp.

That Turkey Story
Mar 30, 2003

Vanadium posted:

This seems really complicated to get right, I think I am going to jump ship into the -fno-rtti -fno-exceptions camp.

Writing exception-safe code is tough, but just keep in mind that turning exceptions off does not absolve you from dealing with exceptional cases. It may seem complicated, but it generally isn't as complicated as manually handling exceptional cases and propagating errors. Proper use of noexcept is also usually pretty simple unless you are dealing with very general templates and really want the function to be noexcept whenever it can be. In those cases, I personally just use a macro that automatically creates the clause (there is also an effort to have some kind of an automatic deduction facility in the next standard).

FamDav
Mar 29, 2008
So let's say I have a class

code:
class Test
{
  // lots of stuff
  operator float*()
}
And I want to write the line

code:
reinterpret_cast<char*>(t) // where t is a Test
I was under the impression that this should correctly cast t to a float*, which has a system defined cast to char*. Why doesn't it?

Adbot
ADBOT LOVES YOU

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.

That Turkey Story posted:

Writing exception-safe code is tough, but just keep in mind that turning exceptions off does not absolve you from dealing with exceptional cases. It may seem complicated, but it generally isn't as complicated as manually handling exceptional cases and propagating errors. Proper use of noexcept is also usually pretty simple unless you are dealing with very general templates and really want the function to be noexcept whenever it can be. In those cases, I personally just use a macro that automatically creates the clause (there is also an effort to have some kind of an automatic deduction facility in the next standard).
This is a good link if you want more info than you wanted to know about using noexcept.
http://akrzemi1.wordpress.com/2011/06/10/using-noexcept/

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