I have some trouble using decltype for member function pointers:
#include <iostream>
#include <type_traits>
struct A
{
void func1() {}
typedef decltype(&A::func1) type;
};
int wmain(int argc, wchar_t* argv[])
{
typedef decltype(&A::func1) type;
//Case 1
std::wcout
<< std::boolalpha
<< std::is_member_function_pointer<type>::value
<< std::endl;
//Case 2
std::wcout
<< std::boolalpha
<< std::is_member_function_pointer<A::type>::value
<< std::endl;
system("pause");
return 0;
}
Case 1 prints true as expected, but Case 2 prints false.
Is decltype stripping away the "member" property of a type? If so, why?
Also, is there a way to prevent this behavior? I need to get the type of a member function regardless of where I use decltype.
Please help.
EDIT:
Reported to Microsoft
For the sake of formality (having an answer to the question), this appears to be a bug in VC2010's compiler. File a bug report so that Microsoft can fix it in the next version.
Related
gcc fails to compile the code below, while clang compiles ok. I have no control on the macro PORTB, as it is in a 3rd party library (avr).
Is it a gcc bug? How can I work around it in gcc? As a workaround is somehow possible to create a pre-processor macro which extracts the numerical value from PORTB?
Note this question is similar, but not identical to my previous question.
It is also different from this question, where the developer has the flexibility to change the rhs of the assignment, thus avoiding the reinterpret_cast.
#include <iostream>
#include <cstdint>
#define PORTB (*(volatile uint8_t *)((0x05) + 0x20))
struct PortB {
static const uintptr_t port = reinterpret_cast<uintptr_t>(&PORTB);
};
int main() {
std::cout << PortB::port << "\n";
return 0;
}
It seems reinterpret_cast is not allowed during compilation. Thus the newer version of the compiler simply is more conforming to the language. reinterpret_cast will not be allowed where a constexpr is required.
But maybe these workaround may help (compiles with g++ 9.2):
#include <iostream>
#include <cstdint>
#define PORTB (*(volatile uint8_t *)((0x05) + 0x20))
struct PortB {
static uintptr_t port;
};
uintptr_t PortB::port = reinterpret_cast<uintptr_t>(&PORTB);
const uintptr_t freePort = reinterpret_cast<uintptr_t>(&PORTB);
#define macroPort reinterpret_cast<uintptr_t>(&PORTB)
int main() {
std::cout << PortB::port << "\n";
std::cout << freePort << "\n";
std::cout << macroPort << "\n";
return 0;
}
The following code has different compile results. From the error message I'm receiving it seems there's a confusion about operators precedence () and <<. I can easily overcome this issue by using a function. However I would like to understand and to know:
a) Which compiler it's evaluating correctly the expression? MSVC2017 seems more logical to me.
b) Is there an workaround still using MACROs?
Full sample code I used.
#include <cstdlib>
#include <typeinfo>
#include <sstream>
#include <iostream>
#ifndef NDEBUG
#define EXPR_INSPECT(param_)\
( (std::ostringstream{} << "< " #param_ " [" << typeid(param_).name() << "] > : " << param_).str() )
#else
#define EXPR_INSPECT(param_)\
(param_)
#endif //NDEBUG
int main(int argc, char *argv[])
{
auto ull_x {99LLU};
std::string string_x {"Checking..."};
std::cout << EXPR_INSPECT( ull_x) << std::endl;
std::cout << EXPR_INSPECT(string_x) << std::endl;
return EXIT_SUCCESS;
}
MSVC2017 works perfectly!
G++ 8.2.0 (MSYS2/MINGW) issues the following error: 'std::basic_ostream::__ostream_type' {aka 'class std::basic_ostream'} has no member named 'str' Attempts to call str() on ostream instead of ostringstream.
EDIT:
The problem here can also be reproduced by clang using Wandbox. Here is a minimal example:
#include <sstream>
#include <iostream>
int main()
{
auto s = std::ostringstream{};
decltype(((std::ostringstream{}) << "< "))::nothing;
decltype((s << "< "))::nothing;
}
In wandbox, clang found the second type std::basic_ostream, while the first type std::basic_ostringstream. That's very strange.
Visual Studio is going crazy on me recently, and gives me the error in the subject when all I did was a simple cout...
CODE:
// Lang.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
int main{
cout << "hi";
}
int main{
cout << "hi";
}
Due to the possibility of initialising objects in C++ with the {} syntax, your compiler probably interprets this code as an attempt to create a global int variable called main, initialised with the result of std::ostream::operator<<, a member function which returns a reference to the std::ostream itself.
It's as if you had written:
double some_variable { cout << "hi" }
Or:
double some_variable { cout }
std::ostream is actually std::basic_ostream<char, std::char_traits<char>>. And that type is not compatible with int.
The only thing which is strange is why the ; after "hi" does not immediately cause the compiler to stop trying; but you don't say which compiler version and which options you are using.
In any case, all of those facts finally result in the error message:
no suitable conversion function from “std::basic_ostream<char,
std::char_traits<char>>” to “int” exists
and in:
Also, the semicolon after "hi" is highlighted, and says "expected a }"
Solution: make main a function:
int main() {
cout << "hi";
}
This is a question regarding the default global namespace in C++. I have the following code that compiles and runs properly using g++ clang-500.2.79.
#include <string>
#include <iostream>
using std::string;
using std::endl;
using std::cout;
bool is_palindrome(const string& str){
return equal(str.begin(), str.end(), str.rbegin());
}
int main(){
cout << "Hello is a palindrome: " << is_palindrome("Hello") << endl;
cout << "madam is a palindrome: " << is_palindrome("madam") << endl;
return 0;
}
My questions is, why does this code compile properly? I forgot to put #include <algorithm> and using std::equal at the beginning of my file. So the expected behaviour is for the compiler to complain.
The example at http://en.cppreference.com/w/cpp/algorithm/equal confirms that I should be using std::equal.
To investigate this further, I tried to track down exactly which version of the equal() function was being called. Being a relative newbie to C++ I don't know exactly how to do this either. I tried,
cout << "The function is: " << equal << endl;
Which generated a compiler error with some interesting information:
/usr/include/c++/4.2.1/bits/stl_algobase.h:771:5:
note: 'std::equal' declared here
Try as I might, I can't find information about stl_algobase (or more probably, I most likely don't understand what I've found). Is stl_algobase a set of functions that are automatically included in the global namespace?
A further questions is: What is the proper way to track (code or otherwise) down which function is being called when you are dealing with potentially overloaded or template functions in C++?
equal is in the std namespace. What you are seeing is argument dependent lookup (ADL). Because the arguments are in the std, the name lookup for equal considers that namespace too.
Here's a simplified example:
namespace foo
{
struct Bar {};
}
namespace foo
{
void bar(const Bar&) {}
void bar(int) {}
}
int main()
{
foo::Bar b;
foo::bar(b); // OK
bar(b); // ADL, OK
foo::bar(42); // OK
bar(42); // No ADL: error: 'bar' was not declared in this scope
}
I manage to use Boost MPL vectors and lists just fine, but I just can't figure out maps. When I try to insert into one, I get "too few arguments" from clang 3.1 (gcc 4.7 says something similar). There is a version of insert where the second argument is POS, which is supposed to be ignored, so I tried inserting a dummy type (int) there, but that just gives a new and confusing error.
include <iostream>
#include <boost/mpl/key_type.hpp>
#include <boost/mpl/map.hpp>
using namespace boost;
using namespace mpl;
int main(){
typedef pair<int_<3>, int_<6>> obj;
std::cout << key_type<map<>, obj >::type::value << std::endl; //works
std::cout << has_key<insert<map<>, obj>::type, obj)::type::value << std::endl; //complains on "too few template arguments for class template 'insert'
std::cout << has_key<insert<map<>, int, obj>::type, obj)::type::value << std::endl; // gives "implicit instantiation of undefined template 'boost::mpl::insert<..."
}
MPL errors aren't exactly helpful, even with clang, so I just don't understand what I am doing wrong here? I am sure it is something silly.
http://www.boost.org/doc/libs/1_51_0/libs/mpl/doc/refmanual/map.html
Add
#include <boost/mpl/insert.hpp>
and correct brackets, from ')' to '>'
http://liveworkspace.org/code/afb6632c3eb800412ea551f50c07fb0a