Why are double parentheses needed with std::is_same [duplicate] - c++

This question already has answers here:
Using commas inside a macro without parenthesis: How can I mix and match with a template?
(3 answers)
Closed 6 years ago.
I was trying to use std::is_same to verify the underlying type of a strongly typed enum and I noticed a strange situation where I needed to use double parentheses, but I don't understand why. I've reduced the example down to as follows:
#include <type_traits>
#include <cassert>
#include <stdint.h>
int main(int argc, char *argv[])
{
assert((std::is_same<unsigned int,uint32_t>::value == true)); // OK
assert((std::is_same<unsigned int,uint32_t>::value) == true); // OK
//assert(std::is_same<unsigned int,uint32_t>::value == true); // Compile error
static_assert(std::is_same<unsigned int,uint32_t>::value == true, "BAD"); // OK
return 0;
}
Compile error:
isSameAssert.cpp:9:62: error: macro "assert" passed 2 arguments, but takes just 1
assert(std::is_same<unsigned int,uint32_t>::value == true); // Compile error
^
isSameAssert.cpp: In function ‘int main(int, char**)’:
isSameAssert.cpp:9:5: error: ‘assert’ was not declared in this scope
assert(std::is_same<unsigned int,uint32_t>::value == true); // Compile error
^
make: *** [build/isSameAssert] Error 1
Could anyone explain this or point me to a reference that does?

Because assert is a macro, the expression assert(std::is_same<unsigned int,uint32_t>::value == true); seems to call assert with two parameters due to the comma between int and uint32_t so the compiler complains that assert takes only one parameter, but two were supplied.
Indeed, putting it again in parenthesis solves this issue.

Related

Confusing behavior with std::is_constructible and if constexpr [duplicate]

This question already has answers here:
Wrong understanding of 'if constexpr'
(2 answers)
if constexpr(condition) as compile-time conditional
(1 answer)
Closed 1 year ago.
Probably easiest to explain if I show an example:
#include <iostream>
#include <type_traits>
class Unconstructible
{
public:
Unconstructible() = delete;
};
int main()
{
if constexpr (std::is_constructible_v<Unconstructible>)
{
std::cout << "Unconstructible is constructible. What?\n";
// Unconstructible foo;
}
else
{
std::cout << "Unconstructible is not constructible.\n";
}
return 0;
}
This outputs "Unconstructible is not constructible" as expected. If, however, I uncomment the line Unconstructible foo;, I get a compilation error:
1>F:\Programming\C++\CppScratchwork\CppScratchwork\CppScratchwork\CppScratchwork.cpp(48): error C2280: 'Unconstructible::Unconstructible(void)': attempting to reference a deleted function
1>F:\Programming\C++\CppScratchwork\CppScratchwork\CppScratchwork\CppScratchwork.cpp(39): message : see declaration of 'Unconstructible::Unconstructible'
1>F:\Programming\C++\CppScratchwork\CppScratchwork\CppScratchwork\CppScratchwork.cpp(39,5): message : 'Unconstructible::Unconstructible(void)': function was explicitly deleted
1>Done building project "CppScratchwork.vcxproj" -- FAILED.
That's in MSVC using /std:c++17. The same behavior shows up on GCC with -std=c++17 but with differently-worded error messages involving attempting to reference a deleted function.
Why is it even attempting to compile the first part of the if constexpr branch? As far as I can tell, it is correctly able to tell that std::is_constructible_v<Unconstructible> is false.

What is purpose of using static_cast<void>()? [duplicate]

This question already has answers here:
what is the use of "static_cast<void>" in macro?
(3 answers)
Why cast unused return values to void?
(10 answers)
Closed 4 years ago.
static_cast<void>() is the 'C++ way' of writing void conversion
In the en.cppreference.com website mentioned as discards the value of the expression. In below link four points on Explanation section
http://en.cppreference.com/w/cpp/language/static_cast
Where and Why should we use static_cast<void>()? give a example..
This is a way to tell that it is ok for a variable to be unused suppressing corresponding compiler warning. This approach has been deprecated with introduction of [[maybe_unused]] attribute in C++17.
The usual purpose of casting to void is to “use” the result of a computation. In relatively strict build environments it is common to output warnings, or even errors, when a variable is declared, maybe even written to, but the result is never used. If, in your code, you know you do not need a result somewhere, you can use the static_cast<void> method to mark the result as discarded – but the compiler will consider the variable used then and no longer create a warning or error.
An example:
#include <iostream>
int myFunction() __attribute__ ((warn_unused_result));
int myFunction()
{
return 42;
}
int main()
{
// warning: ignoring return value of 'int myFunction()',
// declared with attribute warn_unused_result [-Wunused-result]
myFunction();
// warning: unused variable 'result' [-Wunused-variable]
auto result = myFunction();
// no warning
auto result2 = myFunction();
static_cast<void>(result2);
}
When compiled with g++ -std=c++14 -Wall example.cpp, the first two function calls will create warnings.
As VTT pointed out in his post, from C++17 you have the option of using the [[maybe_unused]] attribute instead.

Random number is returned

The following code :
#include <iostream>
using namespace std;
int test()
{
cout<<"question \n";
return 0;
}
int main(){
cout<<test;
}
Output:
question
1
The following code gives 1 everytime I run but I am expecting the output to be 0.
Whereas when I replace the test by test() then I get the expected output. Not sure why is this happening. Please suggest and comment if any rule behind it.
C++ always requires you to use parentheses to call functions. If you omit them, it thinks you want to know the address of the function instead of calling it. The address is then considered to be a (truthy) boolean and gets output as 1. This warning (from gcc -Wall) explains it well:
x.cpp: In function ‘int main()’:
x.cpp:9:11: warning: the address of ‘int test()’ will always evaluate as ‘true’ [-Waddress]
cout<<test;
^
std::cout << test;
Outputs 1 because test is a function pointer, it will be converted to bool with std::cout.

Why is g++ not able to compile tuples? [duplicate]

This question already has answers here:
error: ‘i’ does not name a type with auto [duplicate]
(2 answers)
Closed 6 years ago.
#include <iostream>
#include <tuple>
#include <string>
using namespace std;
int main(){
tuple<string, string, string> x;
x = make_tuple("hi", "a", "b");
cout << get<0>(x) << endl << endl;
}
I've been having difficulties with my program, so I wrote a simpler one and even this does not work. I do not understand why there is a problem after reviewing the documentation several times. It also compiles fine on XCode but for some reason breaks down on g++.
Here is the full error message:
test.cpp:6:3: error: use of undeclared identifier 'tuple'
tuple x;
^
test.cpp:6:9: error: unexpected type name 'string': expected
expression
tuple x;
^
test.cpp:7:3: error: use of undeclared identifier 'x'
x = make_tuple("hi", "a", "b");
^
test.cpp:7:7: error: use of undeclared identifier 'make_tuple'
x = make_tuple("hi", "a", "b");
^
test.cpp:8:11: error: reference to overloaded function could not be
resolved; did you mean to call it? cout << get<0>x << endl << endl;
The command I am using is g++ test.cpp
Try #include <string>.
Possibly (depending on your version og gcc) you also need -std=c++11 on the command line.
The tuple is fine; what you're trying to make it a tuple of is not.
You did not #include <string>!
Thus the word "string" means nothing to your compiler, and it has no idea what you want it to do. It can't even tell that you meant it to be a type, so it can't tell that by the word "tuple" you meant "std::tuple". So on, and so forth…

Why can't I use assert with std::is_same?

Can somebody explain to me why on Earth does this code snippet refuse to work?
#include <cassert>
#include <type_traits>
using namespace std;
int main()
{
assert(is_same<int, int>::value);
}
Compilation fails because, according to the compiler:
prog.cpp:7:33: error: macro "assert" passed 2 arguments, but takes just 1
assert(is_same<int, int>::value);
^
prog.cpp: In function 'int main()':
prog.cpp:7:2: error: 'assert' was not declared in this scope
assert(is_same<int, int>::value);
^
What? is_same<int, int>::value is undoubtedly one argument. Also assert is declared at this scope, and the compiler itself confirmed it in the previous error!
http://ideone.com/LcMVkn
The macro splits your parameter(s) like this:
is_same<int , int>::value
// ^^ par1 ^^// ^^ par2 ^^
As assert() is a macro definition (with one parameter), it's handled by the C-preprocessor. The preprocessor is unaware of c++ syntax like template parameters gouped in angle brackets (<>) separated with ,. So the parameter expression is split up like shown above.
You can avoid that using extra parenthesis, so the C-preprocessor will take that parameter as a whole:
assert((is_same<int, int>::value));
// ^ ^