On Friday 18 June 2004 10:49 am, Helge Hafting wrote: > Angus Leeming wrote: > >Can I choose a value for "d" such that I don't need to modify > > "val" in foo, below? I've tried and failed and so have resorted > > to this runtime modification. > > > > int const a = 1; > > int const b = 2; > > int const c = 4; > > int const d = 8; > > > >void foo(int val) > >{ > > // (val & d) implies (val & b) and (val & c) > > if (val & d) > > val |= b | c; > > ... > >} > > What is it you want to do here? > Do you want to set some bits, or test some bits, or both? > > Your example does "if (val & 8) val |= 6", which cannot be > simplified further. > > Is the stuff in the comment a condition you want to enforce, (your > code does that) > or is it something that is "known to be true" so you want to > simplify the code? > If it is known to always be true then you may remove the entire > if-statement because it does not change anything. It sets bits that > are known to be set already. > > Or am I misunderstanding something?
Ok, let me explain. I have a class which is used to launch, and interact with, a child process. I can interact with the child by writing data to its standard input stream and by reading data from its standard output and standard error streams. Thus, I can define three pipes, identified by typedef int pipe_mode; pipe_mode const child_stdin = 1; pipe_mode const child_stdout = 2; pipe_mode const child_stderr = 4; When I spawn the child process, I want some combination of these pipes to be opened: void process::spawn(string const & command, pipe_mode mode); Usage examples: process ls, wc; ls.spawn("ls -l", child_stdout); wc.spawn("wc -l", child_stdin | child_stdoout); Generally speaking I have two separate pipes to read the child's stdout and stderr. However, I can also redirect output from the child's stderr to stdout. So, I need to augment pipe_mode above: pipe_mode const child_redirect_stderr = X; where X is currently 8. What I'm trying to say is that I can pass any combination of these pipe_mode data to spawn. Eg process.spawn("ls -l", child_stdin | child_stdout | child_stderr | child_redirect_stderr); but that setting child_redirect_stderr *implies* that the pipe to child_stdout is opened and that the pipe to child_stderr is not opened. So, in spawn I currently have the run time check if (mode & child_redirect_stderr) { mode |= child_stdout; if (mode & child_stderr) mode ^= child_stderr; } This works well enough, as exemplified by the attached program. Thereafter, I open pipes with (neglecting error checks) if (mode & child_stdin) ::pipe(child_in_fd); if (mode & child_stdout) ::pipe(child_out_fd); if (mode & child_stderr) ::pipe(child_err_fd); Ie, if child_redirect_stderr is set, the I open child_out_fd and do not open child_err_fd. Finally, in the child process, I set these file descriptors to the child's standard input, output and error streams: pid = ::fork(); switch (pid) { case 0 : // This is the new process. // For each open pipe close one end and redirect the // respective standard stream to the other end if (*child_id_fd >= 0) { ::close(child_in_fd[WR]); ::dup2(child_in_fd[RD], STDIN_FILENO); ::close(child_in_fd[RD]); } if (*child_out_fd >= 0) { ::close(child_out_fd[RD]); ::dup2(child_out_fd[WR], STDOUT_FILENO); ::close(child_out_fd[WR]); } if (*child_err_fd >= 0) { ::close(child_err_fd[RD]); ::dup2(child_err_fd[WR], STDERR_FILENO); ::close(child_err_fd[WR]); } if (*child_out_fd >= 0 && mode & child_redirect_stderr) ::dup2(STDOUT_FILENO, STDERR_FILENO); break; } This works well enough, but I was wondering if, by choosing a different value for child_redirect_stderr, I could avoid the run time check: if (mode & child_redirect_stderr) { mode |= child_stdout; if (mode & child_stderr) mode ^= child_stderr; } Angus
#include <iostream> typedef int pipe_mode; pipe_mode const child_stdin = 1; pipe_mode const child_stdout = 2; pipe_mode const child_stderr = 4; pipe_mode const child_redirect_stderr = 8; void test(std::ostream & os, char const * const name, pipe_mode mode) { if (mode & child_redirect_stderr) { mode |= child_stdout; if (mode & child_stderr) mode ^= child_stderr; } os << "\nmode == " << name << '\n' << "\tmode & child_stdin " << bool(mode & child_stdin) << '\n' << "\tmode & child_stdout " << bool(mode & child_stdout) << '\n' << "\tmode & child_stderr " << bool(mode & child_stderr) << '\n' << "\tmode & child_redirect_stderr " << bool(mode & child_redirect_stderr) << std::endl; } int main() { test(std::cout, "child_stdin", child_stdin); test(std::cout, "child_stdin|child_stdout", child_stdin|child_stdout); test(std::cout, "child_stdin|child_stdout|child_stderr", child_stdin|child_stdout|child_stderr); test(std::cout, "child_stdin|child_stdout|child_redirect_stderr", child_stdin|child_stdout|child_redirect_stderr); test(std::cout, "child_stdin|child_stdout|child_stderr|child_redirect_stderr", child_stdin|child_stdout|child_stderr|child_redirect_stderr); test(std::cout, "child_stdin|child_stderr", child_stdin|child_stderr); test(std::cout, "child_stdin|child_stderr|child_redirect_stderr", child_stdin|child_stderr|child_redirect_stderr); test(std::cout, "child_stdin|child_redirect_stderr", child_stdin|child_redirect_stderr); test(std::cout, "child_stdout", child_stdout); test(std::cout, "child_stdout|child_stderr", child_stdout|child_stderr); test(std::cout, "child_stdout|child_redirect_stderr", child_stdout|child_redirect_stderr); test(std::cout, "child_stdout|child_stderr|child_redirect_stderr", child_stdout|child_stderr|child_redirect_stderr); test(std::cout, "child_stderr", child_stderr); test(std::cout, "child_stderr|child_redirect_stderr", child_stderr|child_redirect_stderr); test(std::cout, "child_redirect_stderr", child_redirect_stderr); return 0; }