Roslyn uses MemberAccessExpressionSyntax instead of QualifiedNameSyntax - roslyn

In the following code, I'd expect that both references to System.Action type to be represented as a QualifiedNameSyntax but the second one is represented as a MemberAccessExpressionSyntax.
Is that correct? If so, why can't it be a QualifiedNameSyntax?
class Foo
{
public void M(object o)
{
var t = typeof(System.Action); // 1
switch(o)
{
case System.Action: // 2
break;
}
}
}

Generally you're only going to get a QualifiedNameSyntax in a Roslyn syntax tree where the only legal thing there is a qualified name; in those cases we're running a restricted parser that will only understand qualified names. Anything else we're running our generic expression parser which will spit out whatever expression is there, and we'll figure out what it actually is during binding. Because consider another case like:
SomeEnum e;
switch (e)
{
case SomeEnum.Blue: Console.WriteLine("Blue!"); return;
}
In that case the SomeEnum.Blue is absolutely an access to a member. But we don't actually know what "SomeEnum" is until binding, so we just always go with MemberAccessExpression.

I can't tell you why for sure, but here's one relevant thing to think about:
In legal code, I think you're right that a switch can never accept a MemberAccessExpression, and so a QualifiedNameSyntax would be sufficient to represent this.
However let's look at some illegal code, and see what happens:
class Foo
{
public static void M(object o)
{
var t = typeof(Foo.M(5)); // 1
switch(o)
{
case Foo.M(5): // 2
break;
}
}
}
This gives 4 errors for the first usage of Foo.M(5):
error CS1026: ) expected
error CS1002: ; expected
error CS1513: } expected
error CS0426: The type name 'M' does not exist in the type 'Foo'
And only 1 for the second:
error CS0426: The type name 'M' does not exist in the type 'Foo'
By allowing a more flexible grammar in the second case, error messages are much better, as they can be done at the semantic level rather than a syntax level.
Since switch expressions accept any pattern as a case, it's more likely that you'll write something invalid, so good error messages are more important in that case.

Related

Is it a good practice to use nested switches in C++? Is there any alternative method to avoid this?

Currently I am having a function which has two arguments of type enums, the function requires to compare both and do particular task
example:
void set_Test_Status(Tests TestName, Status TestStatus)
{
switch(TestName)
{
case Tests::Test1:
{
switch(TestStatus)
{
case TestStatus::St1:
//Rest of Code
}
}
//Rest of Code
}
}
is it a good programming practice? or is there any alternative method or style of coding that i should be aware of? Thank you!
Edit:
Finally after trial and error, I did this. First i saw the maximum and minimum items in each enums, In my case TestName were 6 and TestStatus had 3. I created 3 functions setStatusRunning(Tests TestName), setStatusSelected(Tests TestName) and setStatusFinished(Tests TestName) and in set_Test_status, using switch(TestName) i check which function should be called and then called the appropriate functions. The reason i had to make set_Test_Status in the first place was to make easy for other classes, since i made set_Test_Status public and the other 3 as private.
It is truly a matter of opinion as having nested switch statements is valid c++ code. Some may not have problems with it while others may argue that it can be confusing.
My advice would be on the lines of this; if the code blocks within the case statements are short such as 1-2 lines and they are fairly easy to read and follow, then there should be nothing wrong with it. However, if the code is quite cumbersome and the nested switch statements spans well over 50 to 100+ lines then I would suggest refining your code and make functions out of them.
Examples:
// should be okay
unsigned int outerSwitch = someValue();
unsigned int innerSwitch = someOtherValue();
switch ( outerSwitch ) {
case 1: {
switch ( innerSwitch ) {
case 1 : {
// 1 or 2 lines okay;
}
case 2 : {
// 1 or 2 lines okay;
}
case 3 : {
// 1 or 2 lines okay;
}
default : {
}
} // inner switch when outer switch case = 1
}
case 2: {
// Same as case 1
}
case 3: {
// Same as case 1
}
default: {
}
} // outer switch
But as you have seen above with just 3 cases to the outer and inner; it gets very long very quickly and I haven't even expanded them all. So this can be frowned upon.
You can have a single switch as others have suggested that calls a specific function to that switch then within that function it has its own switch statement like this:
unsigned int someFuncA( unsigned int someVal ) {
switch ( someVal ) {
case 1 : {
// do this
// return that;
}
case 2: {
// ... etc.
}
} // switch
}
unsigned int someFuncB( int someVal ) {
// similar to someFuncA();
}
unsigned int someFuncC( int someVal ) {
// similar to someFuncA();
}
unsigned int switchValue = someValue();
unsigned int innerValue = someOtherFunction();
unsigned int temp = 0;
switch( switchValue ) {
case 1 : {
temp = someFuncA( innerValue );
// either return temp, break, continue, or fall through
}
case 2 : {
temp = someFuncB( innerValue );
// same as above
case 3 : {
temp = someFuncC( innerValue );
// same as above
}
default : {
// default stuff here
}
} // switch
Comparing the two you will see that the 2nd version is easier to read and less cumbersome than the 1st. Yes the first version is valid legal C++ code, but is frowned upon because of how messy it can easily and quickly get. So where ever you can; turn that code into a function that is designed to do just that one thing.
EDIT
Another possibility is to design specific functions to do a task and as you said that your function takes 2 different enumeration values, you can look up the concept of functions that are designed to take bit flags. You will see this kind of code quite a bit in windows programming as well as OpenGL.
Another option is this: consider that fact you have an outer control switch, and inner control switch. Even if you have multiple cases, each case is independent with a specific unique ID. The same can be said for the inner switch cases. Knowing this you can create an associative mapping of all the statements in a combined matter using std::multimap<unsigned, unsigned> testCases and with this lookup table you can have it in a single statement with independent function calls to each map entry. cppreference : std::multimap
Your map might look like this:
testCases[1][1];
testCases[1][2];
testCases[1][3];
testCases[2][1];
testCases[2][2];
testCases[2][3];
testCases[3][1];
testCases[3][2];
testCases[3][3];
Where each index of the map is the logic or calculation you want to perform.
It can be quite confusing for someone reading the code-- indentation helps, but it can still be difficult to follow where the case and switch statements start and end. Most IDEs have support for finding a matching brace, but finding a matching break isn't generally a thing, so it can be difficult to even see where a case statement ends. (And technically case doesn't define scope whereas braces do, so it doesn't even have an end.)
If you get misaligned braces or accidentally mismatch where they should be, you can have odd things happen. Languages like Ada try to prevent that with strongly typed English-language specifiers.
If you are doing a lot of sub-switches, I would put them into another function and call it with the information it needs, then you could do a switch statement inside the method which is more modular, separate scope and clear what is going on.
A good practice to keep code concise is to do only one thing in a function. Using a switch already is a smell that your function is going to do different things. It all depend of your specific case.
One thing to look at is: is it coherent to manage all these cases in one class. Should you have one class per possibility, with an interface forcing to implement a function, instead of doing all the possibilities in a switch case.
In case you want to keep the switch, a good practice would be to not put code in it other than the switch. Each case just calls a function. This will already make stuff more readable.
Finally, are you using all the cases? If no, you code could be more clear by just implementing the pairs of values that you need:
if(TestName == Tests::Test1 && TestStatus == TestStatus::St1)
{
doThing();
}
To summarize:
This might be a smell that your code needs to be split in more classes to have only one responsibility per class (too many if and/or too many switches ar a sign of that). If you are sure that you need a switch, keep it as simple and clear as possible

C++ pqxx postgresql discrete connection classes, scoping class pointer

I have a class, DBProc, which makes a connection to PostgreSQL, and allows user to submit queries/retrieve results.
Functionally, everything works.
The DBProc::connect() function takes an optional argument for connection type. The 3 variants are: direct, lazy, asynchronous.
I have code that instantiates the correct connection class according to user's choice. I initialize 3 unique_ptr<> beforehand, one for each possible connection class, then use an switch statement to choose the selected class type.
This all works fine...but
My preference would be to have ONE class var that holds a reference to
the connection class
(all the classes have the exact same functionality), but I see no easy way to do this.
'auto& currentConnection = lazyConnection' works fine in the switch statement, but of course goes out of scope after the code block.
If there was a way to create a var within a block and allow it to be seen outside the block, without 1st declaring it, that would work, but I don't believe that's possible in c++.
I can't declare it first because all these classes require initialization upon declaration.
So...c++atch 22 ;-)
So, every time I need to use the connection, I need a switch statement to select the right pointer.
I've looked at templates, unions, extern, and don't see a way to do it with any of these.
If anyone knows if there is a way to do this, please describe.
Here's a code snippet of class func:
bool DBProc::connect(ConnectionType type) {
...
unique_ptr<pqxx::connection> connect;
unique_ptr<pqxx::lazyconnection> lzy_connect;
unique_ptr<pqxx::asyncconnection> async_connect;
try
{
switch (type) {
case ConnectionType::direct : {
connect = make_unique<pqxx::connection>(connOpts);
break;
}
case ConnectionType::lazy : {
lzy_connect = make_unique<pqxx::lazyconnection>(connOpts);
break;
}
case ConnectionType::async : {
async_connect = make_unique<pqxx::asyncconnection>(connOpts);
break;
}
} catch
...
}
Working answer provided in comment by 'some programmer dude'
Why not have a std::unique_ptr to pqxx::connection_base which is the common base class for all connection types? – Some programmer dude
Simplified code:
unique_ptr<pqxx::connection_base> base_connect;
try
{
switch (type) {
case ConnectionType::direct : {
base_connect = make_unique<pqxx::connection>(connOpts);
break;
}
case ConnectionType::lazy : {
base_connect = make_unique<pqxx::lazyconnection>(connOpts);
break;
}
case ConnectionType::async : {
base_connect = make_unique<pqxx::asyncconnection>(connOpts);
break;
}
default:
error += "No valid connection type supplied (direct | lazy | async)";
return false;
break;
}

Is there an idiom like `if (Value * value = getValue())` when you branch on an expression of the retrieved value?

I am often using the common
if (Value * value = getValue())
{
// do something with value
}
else
{
// handle lack of value
}
Now, I also often do
QString error = someFunctionReturningAnErrorString(arg);
if (!error.isEmpty())
{
// handle the error
}
// empty error means: no error
That's all fine but I would like the error variable to be scoped to the if-block. Is there a nice idiom for that? Obviously, I can just wrap the whole part inside another block.
This, obviously, does not work:
if(QString error = someFunctionReturningAnErrorString(arg), !error.isEmpty())
{
// handle the error
}
// empty error means: no error
And unfortunately (but for good reasons) the QString cannot be converted to bool, so this does not work either:
if(QString error = someFunctionReturningAnErrorString(arg))
{
// handle the error
}
// empty error means: no error
Any suggestions?
No. There is no idiom like this, and there is no syntax like this!
Besides, you have reached the point at which it is no longer worthwhile to make your code more and more obfuscated.
Simply write it as you do now.
If you really don't want the scope leakage, introduce a new scope:
{
const QString error = someFunctionReturningAnErrorString(arg);
if (!error.isEmpty()) {
// handle the error
}
}
// The above-declared `error` doesn't exist down here
I use this pattern quite a lot, though I've been fairly accused of scope-addiction, so take that as you will.
The only way to use that idiom while still keeping your code understandable is if your function returns an object that is convertible to bool in a way that true indicates that you want to take the branch and false means that you do not care about it. Anything else is just going to lead to write-only code.
One such object which may be relevant happens to be boost::optional. Given:
boost::optional<QString> someFunctionReturningAnErrorString(T arg);
You could use the idiom you want in a natural way:
if (auto error = someFunctionReturningAnErrorString(arg)) {
// ...
}
This also has the added benefit where I'd consider an optional error message more semantically meaningful than having to check for an empty error message.
There is basically no clean way to do that.
I'd recommend you just define an extra block around the if, but if you really want to have that exact syntax, a solution could be to declare your own class wrapping QString:
struct ErrorString
{
ErrorString(QString&& s) : s{move(s)} {}
operator bool() {return !s.isEmpty();}
QString s;
};
And then you could write:
if(ErrorString error = someFunctionReturningAnErrorString(arg))
{
// handle the error
}
// empty error means: no error
But I'm not particularly fond of this solution.
You could use:
for(QString error = someFunctionReturningAnErrorString(arg); !error.isEmpty(); /* too bad 'break' is invalid here */)
{
// handle the error
break;
}
but this is ugly, and makes your code hard to read. So please don't.
if(auto message = maybe_filter( getError(arg), [](auto&&str){
return !str.isEmpty();
}) {
}
where maybe_filter takes a T and a test function and returns optional<T>. The optional<T> is empty if evalutating the test function on the T gives you false, and T otherwise.
Or really, modify your error getting API to return an optional string.
You can use a lambda.
auto error_string_handler = [](QString && error) {
if (error.isEmpty()) return;
//...
}
error_string_handler(someFunctionReturningAnErrorString(arg));

Trying to figure out an alternative method for switch statements

I am currently trying to figure out an alternative method for switch statements as the program I have the switch statements are getting really long and confusing. Therefore I thought it would be a good idea to use array of pointers to functions. I am using c++ and qt. But when I try and implement, I am getting the following error.
cannot convert 'CheckPl::comA' from type 'void (CheckPl::)()' to type 'void (*)()'
It would be much appreciated if someone would help me out with this or at least point me to correct direction.
[...] alternative method for switch statements as the program I have the switch statements are getting really long and confusing.
Extract each case block into a separate function; This way, the switch changes from a 10km long function to a dispatch function:
void dispatch_function()
{
switch(x)
{
case 1: do_case_1(); break;
...
case n: do_case_n(); break;
}
}
Therefore I thought it would be a good idea to use array of pointers to functions.
It's not a good idea (especially, not in the way you went about it - you are solving the xy problem). In C++, when you have a requirement for multiple functions that are called in similar conditions, you have the requirements for an abstract interface.
Your resulting client code should look like this:
std::vector<handlers> handlers; // filled with handler instances, one for each case
for(const auto& h: handlers) // replaces switch
if(h.fits_case(x)) // replaces case statement
{
h.do_case(x); // replaces case block
break;
}
It follows that your handler classes should inherit from a base class like this:
class handler_base
{
virtual bool fits_case(int x) = 0;
virtual void do_case(int x) = 0;
}
This is easy to understand (in both implementation and client code), it is modular, testable (you can test each case separately) and extensible (if you need a new case you only add the case and add it to the vector); It also doesn't use any pointers.
A pointer to a member function has to be stored in a variable of the appropriate type. A pointer to a member function is not compatible with a pointer to a function.
void (CheckPl::*mptr)() = &CheckPl::comA;
A pointer to a member function requires an instance to an object for invocation.
CheckPl c;
CheckPl *cp = &c;
(c.*mptr)();
(cp->*mptr)();
The hardest thing to remember about the above syntax is that the extra set of parentheses is required.

How would you use Alexandrescu's Expected<T> with void functions?

So I ran across this (IMHO) very nice idea of using a composite structure of a return value and an exception - Expected<T>. It overcomes many shortcomings of the traditional methods of error handling (exceptions, error codes).
See the Andrei Alexandrescu's talk (Systematic Error Handling in C++) and its slides.
The exceptions and error codes have basically the same usage scenarios with functions that return something and the ones that don't. Expected<T>, on the other hand, seems to be targeted only at functions that return values.
So, my questions are:
Have any of you tried Expected<T> in practice?
How would you apply this idiom to functions returning nothing (that is, void functions)?
Update:
I guess I should clarify my question. The Expected<void> specialization makes sense, but I'm more interested in how it would be used - the consistent usage idiom. The implementation itself is secondary (and easy).
For example, Alexandrescu gives this example (a bit edited):
string s = readline();
auto x = parseInt(s).get(); // throw on error
auto y = parseInt(s); // won’t throw
if (!y.valid()) {
// ...
}
This code is "clean" in a way that it just flows naturally. We need the value - we get it. However, with expected<void> one would have to capture the returned variable and perform some operation on it (like .throwIfError() or something), which is not as elegant. And obviously, .get() doesn't make sense with void.
So, what would your code look like if you had another function, say toUpper(s), which modifies the string in-place and has no return value?
Have any of you tried Expected; in practice?
It's quite natural, I used it even before I saw this talk.
How would you apply this idiom to functions returning nothing (that is, void functions)?
The form presented in the slides has some subtle implications:
The exception is bound to the value.
It's ok to handle the exception as you wish.
If the value ignored for some reasons, the exception is suppressed.
This does not hold if you have expected<void>, because since nobody is interested in the void value the exception is always ignored. I would force this as I would force reading from expected<T> in Alexandrescus class, with assertions and an explicit suppress member function. Rethrowing the exception from the destructor is not allowed for good reasons, so it has to be done with assertions.
template <typename T> struct expected;
#ifdef NDEBUG // no asserts
template <> class expected<void> {
std::exception_ptr spam;
public:
template <typename E>
expected(E const& e) : spam(std::make_exception_ptr(e)) {}
expected(expected&& o) : spam(std::move(o.spam)) {}
expected() : spam() {}
bool valid() const { return !spam; }
void get() const { if (!valid()) std::rethrow_exception(spam); }
void suppress() {}
};
#else // with asserts, check if return value is checked
// if all assertions do succeed, the other code is also correct
// note: do NOT write "assert(expected.valid());"
template <> class expected<void> {
std::exception_ptr spam;
mutable std::atomic_bool read; // threadsafe
public:
template <typename E>
expected(E const& e) : spam(std::make_exception_ptr(e)), read(false) {}
expected(expected&& o) : spam(std::move(o.spam)), read(o.read.load()) {}
expected() : spam(), read(false) {}
bool valid() const { read=true; return !spam; }
void get() const { if (!valid()) std::rethrow_exception(spam); }
void suppress() { read=true; }
~expected() { assert(read); }
};
#endif
expected<void> calculate(int i)
{
if (!i) return std::invalid_argument("i must be non-null");
return {};
}
int main()
{
calculate(0).suppress(); // suppressing must be explicit
if (!calculate(1).valid())
return 1;
calculate(5); // assert fails
}
Even though it might appear new for someone focused solely on C-ish languages, to those of us who had a taste of languages supporting sum-types, it's not.
For example, in Haskell you have:
data Maybe a = Nothing | Just a
data Either a b = Left a | Right b
Where the | reads or and the first element (Nothing, Just, Left, Right) is just a "tag". Essentially sum-types are just discriminating unions.
Here, you would have Expected<T> be something like: Either T Exception with a specialization for Expected<void> which is akin to Maybe Exception.
Like Matthieu M. said, this is something relatively new to C++, but nothing new for many functional languages.
I would like to add my 2 cents here: part of the difficulties and differences are can be found, in my opinion, in the "procedural vs. functional" approach. And I would like to use Scala (because I am familiar both with Scala and C++, and I feel it has a facility (Option) which is closer to Expected<T>) to illustrate this distinction.
In Scala you have Option[T], which is either Some(t) or None.
In particular, it is also possible to have Option[Unit], which is morally equivalent to Expected<void>.
In Scala, the usage pattern is very similar and built around 2 functions: isDefined() and get(). But it also have a "map()" function.
I like to think of "map" as the functional equivalent of "isDefined + get":
if (opt.isDefined)
opt.get.doSomething
becomes
val res = opt.map(t => t.doSomething)
"propagating" the option to the result
I think that here, in this functional style of using and composing options, lies the answer to your question:
So, what would your code look like if you had another function, say toUpper(s), which modifies the string in-place and has no return value?
Personally, I would NOT modify the string in place, or at least I will not return nothing. I see Expected<T> as a "functional" concept, that need a functional pattern to work well: toUpper(s) would need to either return a new string, or return itself after modification:
auto s = toUpper(s);
s.get(); ...
or, with a Scala-like map
val finalS = toUpper(s).map(upperS => upperS.someOtherManipulation)
if you don't want to follow a functional route, you can just use isDefined/valid and write your code in a more procedural way:
auto s = toUpper(s);
if (s.valid())
....
If you follow this route (maybe because you need to), there is a "void vs. unit" point to make: historically, void was not considered a type, but "no type" (void foo() was considered alike a Pascal procedure). Unit (as used in functional languages) is more seen as a type meaning "a computation". So returning a Option[Unit] does make more sense, being see as "a computation that optionally did something". And in Expected<void>, void assumes a similar meaning: a computation that, when it does work as intended (where there are no exceptional cases), just ends (returning nothing). At least, IMO!
So, using Expected or Option[Unit] could be seen as computations that maybe produced a result, or maybe not. Chaining them will prove it difficult:
auto c1 = doSomething(s); //do something on s, either succeed or fail
if (c1.valid()) {
auto c2 = doSomethingElse(s); //do something on s, either succeed or fail
if (c2.valid()) {
...
Not very clean.
Map in Scala makes it a little bit cleaner
doSomething(s) //do something on s, either succeed or fail
.map(_ => doSomethingElse(s) //do something on s, either succeed or fail
.map(_ => ...)
Which is better, but still far from ideal. Here, the Maybe monad clearly wins... but that's another story..
I've been pondering the same question since I've watched this video. And so far I didn't find any convincing argument for having Expected, for me it looks ridiculous and against clarity&cleanness. I have come up with the following so far:
Expected is good since it has either value or exceptions, we not forced to use try{}catch() for every function which is throwable. So use it for every throwing function which has return value
Every function that doesn't throw should be marked with noexcept. Every.
Every function that returns nothing and not marked as noexcept should be wrapped by try{}catch{}
If those statements hold then we have self-documented easy to use interfaces with only one drawback: we don't know what exceptions could be thrown without peeking into implementation details.
Expected impose some overheads to the code since if you have some exception in the guts of your class implementation(e.g. deep inside private methods) then you should catch it in your interface method and return Expected. While I think it is quite tolerable for the methods which have a notion for returning something I believe it brings mess and clutter to the methods which by design have no return value. Besides for me it is quite unnatural to return thing from something that is not supposed to return anything.
It should be handled with compiler diagnostics. Many compilers already emit warning diagnostics based on expected usages of certain standard library constructs. They should issue a warning for ignoring an expected<void>.