Is there a way to check if class
has a typedef
which works even for private
typedef
?
Following code works in VS2013, but fails on ideone's gcc
template<typename T>
struct to_void
{
typedef void type;
};
class Foo
{
typedef int TD;
};
template <typename T, typename dummy = void>
struct has_TD : std::false_type {};
template <typename T>
struct has_TD<T, typename to_void<typename T::TD>::type > : std::true_type{};
int main()
{
std::cout << std::boolalpha << has_TD<Foo>::value << std::endl;
}
edit - why I want this
I have custom serialization system, which can serialize arbitrary type. It has several overloads when it must behave differently (for example string). For the rest of the types, it simply writes the value in the memory. If I have composed type, I can sometimes just write into memory as well (save & load happens on the same architecture, compiled with the same compiler, so paddings will be the same, etc.). This method is valid for example for POD types (std::is_pod
trait), but all POD types is only a subset of all types, supporting this serialization.
So I basically have templated function write<T>
which just write sizeof(T)
bytes (raw-serialization)... But I don't want this to be called by mistake, I want user, to explicitly say in their class: "this class/struct can be raw-serialized"). The way I do it is a macro ALLOW_RAW_SERIALIZE
which defines some typedef which can be checked via trait. If class MyClass
doesn't contains typedef, calling write(myClassInstance)
will produce compiler error.
The things which which basically decide if class can be raw-serialized are its members (without reflection, members cannot be enumerated and checked automatically, so user have to provide such information). typical class looks like this:
class
public
ctor-dtor
methods
private
methods
members
and I want users to allow write ALLOW_RAW_SERIALIZE
as close to the members as possible, so when they change some members there is a lesser chance to forgot about updating ALLOW_RAW_SERIALIZE
(remove it. when it's no longer valid)
So that is why I want to check a private typedef
Since it's substitute for reflection and takes whole type and write it, I don't fell about it like breaking encapsulation or so...
UPDATE:
Okay, did a little research.
FYI, the [probable] reason that ideone
didn't compile is that what you're doing needs -std=c++11
[or higher]. I got similar errors before adding that. But, I had to use clang++
as g++
still had problems compiling if TD
was private
.
But, I'm not sure this works as the only combo that printed true was if TD
was public. All others of public/private and changing TD
to TF
produced false. Maybe VS2013 works [why?], but two other compilers have issues, either in compilation or runtime results--YMMV.
The basis for what you're doing is std::integral_constant
[since c++11]. There appears to be no standard derivation from this for what you're doing. That is, from http://www.cplusplus.com/reference/type_traits/integral_constant/ the list of type traits [on the left] has nothing that matches your use case [AFAICT].
Nor does Boost.TypeTraits
have anything that matches up [again, AFAICT].
From Andrei Alexandrescu's book: "Modern C++ Design: Generic Programming and Design Patterns Applied", section 2.10 Type Traits:
Usually, you will write your own trait templates and classes as your generic code needs them. Certain traits, however, are applicable to any type. They can help generic programmers to tailor template code better to the capabilities of a type.
So, it's "okay" to roll your own, if you wish.
But, even the TypeTraits
he talks about [from Loki], again, doesn't have anything that matches what you're doing.
Since neither std
nor Boost
has anything, then the question becomes "what is standard?" [from your perspective]. There may be "fludger" c++ traits library somewhere that has an implementation, but would that be considered "standard"? YMMV
However, a question or two:
Why would one do this? What is the use for it? What about a protected typedef in a base class?
And, this seems to require knowledge of the private part of a class, and wouldn't that be a violation of either "data hiding" or encapsulation [without a friend
declaration of some sort]?
So, if that last question is true, the probable [IMO] answer is that there is no standard way to do this, because it's not something one should be doing in a standard library.
Side note: This is the part that got downvoted (before I [truly] understood the question). I believe I've acquitted myself above. So, disregard the answer below.
When you use class
the default visibility is private
. With struct
, it's public
.
So, either do:
struct Foo
Or:
class Foo
{
public:
typedef int TD;
};
This is, of course, assuming that you want TD
to be public
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With