The following code
#include <iostream>
#include <new>
#include <cstring>
#include <type_traits>
template<typename T>
void is_pod(char* c)
{
cout << "Type " << c;
if(std::is_pod<T>::value)
::std::cout << " is POD" << endl;
else
::std::cout << " is not!" << endl;
}
#define CHECK_TYPE(ty) ::is_pod<ty>(#ty)
struct POD_Parent{};
struct POD_Child : public POD_Parent{int y;};
struct POD_Child2 {int x; POD_Parent y; POD_Child ssd;};
int main()
{
CHECK_TYPE(POD_Parent);
CHECK_TYPE(POD_Child);
CHECK_TYPE(POD_Child2);
Gives the following results: Which is strange!
Type POD_Parent is POD
Type POD_Child is not!
Type POD_Child2 is POD
How can POD_Child is not POD?! and POD_Child2 is POD?!!
Note that I compiled it using MinGW (using option -std=c++11) and it said that all of them are POD.
According to [MSDN][1] a type that has a base class is not POD so POD_Child is not POD but for POD_Child2 its possibly some mistake of the compiler that ignore base class of ssd
Related
i have this piece of code (http://coliru.stacked-crooked.com/a/ee05a00fc8ab5057):
#include <type_traits>
struct unregistered;
unregistered register_type(...);
template<class T>
constexpr bool is_registered = !std::is_same_v<unregistered, decltype(register_type(std::declval<T>()))>;
template<class T>
struct test_registration
{
static_assert(is_registered<T>, "Type is not registered!");
};
struct foo{};
struct bar{};
void register_type(int);
void register_type(char);
void register_type(void*);
void register_type(foo);
void register_type(foo*);
#include <boost/core/demangle.hpp>
#include <iostream>
int main()
{
std::cout << boost::core::demangle(typeid(test_registration<foo>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<foo*>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<int>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<char>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<void*>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<long>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<bar>).name()) << "\n";
return 0;
}
The compiler generates errors for the calls using int, char, void*, long and bar.
I expect the errors for long and bar.
What I do not understand is:
Why are int, char, and foo treated differently?
Why are void*, and foo* treated differently? (both are ptrs)
I assume the reason has to do with foo beeing class type and int and char beeing plain types.
I would like to know the reason. Is it a compiler bug or is there some passage in the standard explaining this behaviour?
What I am asking is not how I can fix this problem (see link to coliru for a fix).
What I want to know is why it is behaving like this.
How come the following code compiles with gcc-4.8 with no problem, while using clang-3.6 generates appropriate error:
"error: 'value_type' is a private member of 'B'"
#include <iostream>
#include <type_traits>
struct B {
private:
typedef int value_type;
};
int main () {
std::cout << std::is_same< B::value_type, int >::value << std::endl;
}
In this sample code, there is two sentences showing the same static variable. The first one gives no ambiguity, but the second one does, why?
#include <iostream>
using namespace std;
struct A { static const char a = 'a'; };
struct B : public A { };
struct C : public A { };
struct G : public B, public C { };
int main()
{
G v;
cout << G::B::A::a << endl;
cout << v.B::A::a << endl;
}
GCC error (according to some comments, there's no ambiguity in clang):
main.cpp:15:18: error: 'A' is an ambiguous base of 'G'
cout << v.B::A::a << endl;
Code on coliru
This is clearly a bug in GCC, as a GCC maintainer recommends you report it. However, until it's fixed, you can use a nasty workaround like this:
std::cout << static_cast<B &>(v).A::a;
The advantage is this will help disambiguate if in a (complex) scenario that there are variables with the same name in one of the base classes.
I have succeeded writing a class like this one, capturing this in a lambda defined as non-static attribute of said class:
#include <memory>
#include <iostream>
#include <functional>
struct S
{
S()
{
std::cout << "S::S()[" << this << "]" << std::endl;
}
std::string y_{"hi mate"};
int x_;
std::function<void(int*)> del_{[this](int *ptr)
{
std::cout << "Deleting ptr[" << ptr << "] this[" << this << "] this->y_[" << this->y_ << "]" << std::endl;
}};
std::unique_ptr<decltype(x_), decltype(del_)> unique_{&x_, del_};
};
int main()
{
S s;
}
This compiles and seems to run just fine.
However, with a templated class, it doesn't work anymore:
#include <memory>
#include <iostream>
#include <functional>
template <typename>
struct S
{
S()
{
std::cout << "S::S()[" << this << "]" << std::endl;
}
std::string y_{"hi mate"};
int x_;
std::function<void(int*)> del_{[this](int *ptr)
{
std::cout << "Deleting ptr[" << ptr << "] this[" << this << "] this->y_[" << this->y_ << "]" << std::endl;
}};
std::unique_ptr<decltype(x_), decltype(del_)> unique_{&x_, del_};
};
int main()
{
S<int> s;
}
$> g++ -std=c++1y custom_deleter_template.cpp
~/test custom_deleter_template.cpp: In instantiation of ‘struct
S::’: custom_deleter_template.cpp:9:3: required
from ‘S< >::S() [with
= int]’ custom_deleter_template.cpp:24:10:
required from here custom_deleter_template.cpp:15:35: internal
compiler error: in tsubst_copy, at cp/pt.c:12569
std::function del_{[this](int *ptr)
^ Please submit a full bug report, with preprocessed source if appropriate. See
for instructions.
Preprocessed source stored into /tmp/pyro/ccxfNspM.out file, please
attach this to your bugreport.
Before filing a bugreport (which I can't do, they blocked account creation), is it normal that it does not compile, based on what the standard says?
Compiler is g++ (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2, used flag -std=c++1y. Same thing happens with flag -std=c++11.
This is indeed a bug in GCC, which is already being tracked.
It seems to affect 4.8 and 4.9. As pointed out in the comments this particular example works fine for 4.7 and 5.0. You can see that for yourself here and play with the different versions of gcc.
However this reduced version of your code with no external dependency still crashes with 5.0:
template <typename>
struct S {
int f{[this](){return 42;}()};
};
int main(){
return S<int>{}.f; // should return 42
}
I would suggest that you wait for the bug I referenced to be fixed before using your code, or switch to another compiler ;).
Why this code produces a false output?
//this-type.cpp
#include <iostream>
#include <type_traits>
using namespace std;
template<typename testype>
class A
{
public:
A()
{
cout << boolalpha;
cout << is_same<decltype(*this), A<int>>::value << endl;
}
};
class B : public A<int>
{
};
int main()
{
B b;
}
Output:
$ g++ -std=c++11 this-type.cpp
$ ./a.out
false
The type of "*this" inside A through B is A< int >, isn't it?
*this is an lvalue of type A, so decltype(*this) will give the reference type A &. Recall that decltype on an lvalue gives the reference type:
cout << is_same<decltype(*this), A<int>>::value << endl;
cout << is_same<decltype(*this), A<int> &>::value << endl;
Output:
false
true
Try:
typedef std::remove_reference<decltype(*this)>::type this_type;
cout << is_same<this_type, A<int>>::value << endl;
and maybe remove_cv in some other contexts (if you don't care about const/volatile) like this:
typedef std::remove_reference<decltype(*this)>::type this_type;
typedef std::remove_cv<this_type>::type no_cv_this_type;
cout << is_same<no_cv_this_type, A<int>>::value << endl;
Are you sure decltype(*this) is A ? You should investigate on that with an ugly cout debug line.