Able to access private data members with gcc, while clang complains appropriately - c++

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;
}

Related

Access type through another type in the same namespace

I have two structs A and B that live in the same namespace. For architectural and compatibility reasons I want to have A accessible through B.
I tried the following which is not working:
#include <iostream>
struct A
{
static void print()
{
std::cout << "hello SO!" << std::endl;
}
};
struct B
{
typedef A A; // error here
};
int main()
{
B::A::print();
return 0;
}
Apparently the typedef to the same name is not working. With g++ I get the following error:
foo.cpp:13:15: error: declaration of ‘typedef struct A B::A’ [-fpermissive]
typedef A A;
^
foo.cpp:3:8: error: changes meaning of ‘A’ from ‘struct A’ [-fpermissive]
struct A
It would work if I give it an other name (e.g. typedef A A2) but I want it to keep the same name.
Interestingly, it is actually working when I compile with clang but I would need code that also builds with gcc.
Is there some way to achieve this (i.e. being able to do B::A::print())?
I am currently using C++11 but going to a newer version might be possible if it is necessary.
just use typedef ::A A or using A = ::A
https://godbolt.org/z/VVKk3V
Here is a solution:
#include <iostream>
namespace NS {
struct A {
static void print() { std::cout << "hello SO!" << std::endl; }
};
struct B {
using A = NS::A;
};
} // namespace NS
int main() {
NS::B::A::print();
return 0;
}
Compiles fine.

Collision of nested typenames in MSVC

I have encountered a problem while was using variadic templates, but the problem is not related to variadic templates and can be reproduced without them.
The problem is related to same names of types in inherited and base classes.
I've simplified code to the following snippet:
#include <typeinfo>
#include <iostream>
struct A
{
int member;
};
struct B: public A
{
typedef A NEXT;
short member;
};
struct Foo: public B
{
typedef B NEXT;
void Check()
{
std::cout << typeid(NEXT::member).name() << '\n';
std::cout << typeid(NEXT::NEXT::member).name() << '\n';
NEXT::NEXT::member = 1;
NEXT::member = 2;
std::cout << NEXT::NEXT::member << '\n';
std::cout << NEXT::member << '\n';
};
};
int main()
{
Foo foo;
foo.Check();
}
It compiles without warnings and works with GCC and clang, but it produces wrong output with MSVC (at least with Visual Studio 2015 Update 1).
It seems that some collision in names happens, and it treats NEXT::NEXT::member as NEXT::member, but in the same place, it lies to typeid (as well as to std::is_same).
When compiled with GCC or clang the output is:
s
i
1
2
But in case of MSVC, the output is:
short
int
2
2
The following code compiles without warnings with GCC or clang, but as expected produces error with MSVC:
struct A
{
int member;
};
struct B: public A
{
typedef A NEXT;
short member;
};
struct Foo: public B
{
typedef B NEXT;
short& GetB() { return NEXT::member; };
int& GetA() { return NEXT::NEXT::member; };
};
The MSVC error:
source_file.cpp(18): error C2440: 'return': cannot convert from 'short' to 'int &'
Is the code above valid? Is it a problem of MSVC or I'm utilizing UB somehow?
Update
The problem can not be reproduced in MSVC 2015 update 3.

Why does my attempt at detecting static members using SFINAE appear not to work?

I've just made a template to detect if a data member of a class is static defined or not. The accessibility of the member isn't what it should be concerned about(Assuming the member is always accessible by the template) in this post. Here is the code with any symbols for testing:
#include <conio.h>
//#include <stdio.h>
#include <iostream>
struct A1
{
int a;
};
struct A2
{
static int a;
};
int A2::a{};
template < class My_Type >
struct TestStatic
{
template < typename raw_ty > static char fTest(...);
template < typename class_ty, typename arg_ty = decltype(class_ty::a) >
static int fTest(int, arg_ty & = class_ty::a);
enum nRes { result = sizeof(fTest<My_Type>(0)) - 1 };
};
int main(void)
{
int i;
i = TestStatic<A1>::result;
std::cout << i << std::endl;
i = TestStatic<A2>::result;
std::cout << i << std::endl;
_getch();
return(0);
}
The question is when it was built with g++ 4.8 the compiling passed but got the result as two '3's rather than one '0' and another '3'. Is there anything wrong?
Your approach is fundamentally flawed, because decltype(T::x) is perfectly valid for non-static members:
#include <iostream>
struct T
{
int x;
};
int main()
{
std::cout << sizeof(decltype(T::x)) << '\n';
}
// Output: 4
You can get what you want with std::is_member_pointer:
If T is pointer to non-static member object or a pointer to non-static member function, provides the member constant value equal true. For any other type, value is false.
#include <iostream>
#include <type_traits>
struct T
{
int x;
};
struct S
{
static int x;
};
int main()
{
std::cout << !std::is_member_pointer<decltype(&T::x)>::value << ' ';
std::cout << !std::is_member_pointer<decltype(&S::x)>::value << '\n';
}
// Output: 0 1
This works because access to members through the :: syntax results in a pointer-to-member only if the member is not-static; it is of course a normal variable access when the member is static.

POD in Visual Studio 2008

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

Is this name lookup in dependent base class with VC++ 2010 non-standard?

The code below does not compile on Ideone or Codepad, yielding errors like:
'X' was not declared in this scope
but it does on VC++ 2010:
#include <iostream>
#include <typeinfo>
template<typename T>
struct Base
{
typedef T X;
};
template<typename T>
struct Derived
:
Base<T>
{
static void print()
{
std::cout << typeid(X).name() << "\n";
}
};
int main()
{
Derived<int>::print();
Derived<char>::print();
Derived<float>::print();
return 0;
}
where it prints int, char and float. Should I change my code to:
template<typename T>
struct Derived
{
typedef Base<T> B;
static void print()
{
std::cout << typeid(typename B::X).name() << "\n";
}
};
in order to be standard-conforming?
If you meant the equivalent of this (note you have dropped the inheritance in your example):
template<typename T>
struct Derived : Base<T> {
static void print() {
std::cout << typeid(typename Base<T>::X).name() << "\n";
}
};
then yes, that is standard compliant code. But note that the result of typeid(some type).name() is implementation dependent. On GCC your main produces i, c and f.
$ g++ -Wall test.cpp
test.cpp: In static member function 'static void Derived::print()':
test.cpp:15:37: error: 'X' was not declared in this scope
$ g++ --version
g++ (SUSE Linux) 4.6.2