I would like to use something like typedef in my C++ programs to enhance type safety.
As an example, suppose I have two functions
void function1(unsigned idOfType1);
void function2(unsigned idOfType2);
then I can mistakenly pass idOfType2 to function1 and vice versa. I want the compiler to give me an error in this case. I am aware that I could wrap these unsigned in a struct, but then I'd have to give provide a field name and use . to access them, which is slightly inconvenient. Is there a good way around this?
Edit: As far as I know typedef will not work for this purpose as it is just a shorthand for a type and will not be used for type checking.
Use Boost strong typedef:
typedef creates an alias for an existing type. It does not create a new type that can be used for matching either function or template parameters...
Usage of BOOST_STRONG_TYPEDEF addresses this...
BOOST_STRONG_TYPEDEF is a macro which generates a class named "name" wraps and instance of its primitive type and provides appropriate conversion operators in order to make the new type substitutable for the one that it wraps.
As you say, a typedef won't help you here. I can't think of a better way immediately, however if you go with your wrapping in a struct/class option you could use a conversion operator to eliminate the member method or function call.
For example:
struct WrappedType
{
operator type()
{
return _value;
}
type _value;
}
I'm not saying this is the way to do it mind you ;-)
This is a late reply to an old question. But there are new developments on the C++ front and for the sake of completeness I'm adding this answer:
The opaque_typedef library is the author's attempt to provide most of the value of opaque typedefs through a library, without waiting for opaque typedefs to become a language feature.
The author of this library, Kyle Markley had a short brilliant speech at the cppcon 2015 introducing this library. The slides of his speech are on github the source code of the library is available on sourceforge. The library is header-only, written in C++11. Gcc and clang are ok, but VS2015 seems to have problems with it.
The use of the library is straight-forward. The following code was taken from the documentation. It creates an opaque typedef of int. It has the same interface as an int (it can be added, shifted, incremented, compared, etc.) but the arguments and return values are of the newly-created type, not of int:
#include "opaque/numeric_typedef.hpp"
struct myint : opaque::numeric_typedef<int, myint> {
using base = opaque::numeric_typedef<int, myint>;
using base::base;
};
There is a c++11 feature called enum class, which is basically a type safe enum. Maybe they can help here.
In foonathan's blog post from 2016 various approaches are covered, starting with an example class for simple cases:
class meter
{
public:
explicit meter(int val)
: value_(val) {}
explicit operator int() const noexcept
{
return value_;
}
private:
int value_;
};
and ending with a short template library with arithmetic support for custom type-safe types, allowing one to write this:
struct meter
: strong_typedef<meter, int>, addition<meter>
{
using strong_typedef::strong_typedef;
};
You can check the type in your function, so that if it didn't match, you can print an error or something.
You can use typeid to detect variable type, as follows:
typeid(*variablename*).name()
As suggested in one of the answers here, this is compiler-dependent and you have to use try-and-error method to find out which value works for you.
Related
I know how to get the type of a function's parameter the old way, but I was wondering if there is a nice new way to do it with Hana? For example, I want something like this:
struct foo {
int func(float);
};
auto getFuncType(auto t) -> declval<decltype(t)::type>()::func(TYPE?) {}
getFunType(type_c<foo>); // should equal type_c<float> or similar
How do I get the TYPE here?
Edit 6/21/2016 - Minor changes to match current version of library (0.4).
I'm the author of CallableTraits, the library mentioned above by #ildjarn (although it is not yet included in Boost). The arg_at_t metafunction is the best way that I know to get the parameter type from a member function, function, function pointer, function reference, or function object/lambda.
Please keep in mind that the library is currently undergoing significant changes, and that the linked documentation is somewhat outdated (i.e. use at your own risk). If you use it, I recommend cloning the develop branch. For the feature you are seeking, the API will almost certainly not change.
For member function pointers, arg_at_t<0, mem_fn_ptr> aliases the equivalent of decltype(*this), to account for the implicit this pointer. So, for your case, you would do this:
#include <type_traits>
#include <callable_traits/arg_at.hpp>
struct foo {
int func(float);
};
using func_param = callable_traits::arg_at_t<1, decltype(&foo::func)>;
static_assert(std::is_same<func_param, float>::value, "");
int main(){}
Then, you can put it into a boost::hana::type or whatever your use case requires.
Live example
I need to create an union, but 2 members of the union would have the same type, thus I need a way to identify them. For example in OCaml :
type A =
| B of int
| C of float
| D of float
Boost.Variant doesn't seem to support this case, is there a known library which supports that ?
If you want to do this, I think your best option is to wrap the same-but-different-types into a struct which then lets the boost variant visit the proper one:
struct Speed
{
float val_;
};
struct Darkness
{
float val_;
};
You might be able to use BOOST_STRONG_TYPEDEF to do this automatically but I'm not sure it's guaranteed to generate types legal for use in a union (although it would probably be fine in a variant).
You cannot at the moment but C++17's implementation of std::variant fortunately allows it:
A variant is permitted to hold the same type more than once, and to hold differently cv-qualified versions of the same type.
Unlike with the boost version, you can get values by index, something like this (not tested):
// Construct a variant with the second value set.
variant<string, string, string> s(std::in_place_index<1>, "Hello");
// Get the second value.
string first = std::get<1>(s);
Michael Park has written a C++14 implementation of C++17's std::variant.
The c++ code here:
http://svn.boost.org/svn/boost/sandbox/variadic_templates/boost/composite_storage/pack/container_one_of_maybe.hpp
is truly a tagged union in that it can contain duplicate types. One nice feature
is the tags can be enumerations; hence, the tags can have meaningful names.
Unfortunately, the compile time cost is pretty bad, I guess, because the implementation
uses recursive inheritance. OTOH, maybe compilers will eventually figure out a way
to lessen the compile time cost.
OTOH, if you want to stick with boost::variant, you could wrap the types,
as Mark B suggested. However, instead of Mark B's descriptive class names,
which require some thought, you could use fusion::pair<mpl::int_<tag>,T_tag>
where T_tag is the tag-th element in the source fusion::vector. IOW:
variant
< fusion::pair<mpl::int_<1>,T1>
, fusion::pair<mpl::int_<2>,T2>
...
, fusion::pair<mpl::int_<n>,Tn>
>
As the fusion docs:
http://www.boost.org/doc/libs/1_55_0/libs/fusion/doc/html/fusion/support/pair.html
say, fusion::pair only allocates space for the 2nd template argument; hence,
this should not take any more room than boost::variant<T1,T2,...,Tn>.
HTH.
-regards,
Larry
I have a class that contains a private typedef and several member
functions:
class Foo
{
private:
typedef std::blahblah FooPart;
FooPart m_fooPart;
...
public:
int someFn1();
int someFn2();
};
Several member functions need to use m_fooPart in a similar way, so I
want to put that in a function. I put helper functions in the anonymous
namespace whenever I can, but in this case, they need to know what
FooPart is. So, I've done this:
namespace
{
template <typename T>
int helperFn(const T& foopart, int index)
{
...
return foopart.fn(index);
}
}
int Foo::someFn1()
{
...
return helperFn(m_fooPart, ix);
}
By forcing the compiler to produce the FooPart type, am I still in the
land of well-defined behavior? Is there a more elegant way of
accomplishing this that doesn't increase the size of Foo or make public
what is now private?
Yes, that approach produces well-defined, standards-compliant behavior.
That said, adding member functions to a class does not increase the size of a class (assuming you mean the result of the sizeof operator), so I'm not sure what drawback you perceive in just making the helper function a private member of Foo.
Simple answer: make the typedef public.
That will leak a minor detail of implementation (the actual internal type), but because it is typedefed you can redefine it at any time and it should be fine.
A little less simple: befriend the helper function, providing access to your internal type.
The problem with this second approach is that you are not only granting access to the typedef, but also to all the private parts of your class, and that might not be the best idea. At any rate, since this is an internal helper function, it is under your own control, and it should be fine. (Now that I think of it, you might want to declare the function in a named namespace, for the friend declaration to succeed)
Even less simple: Create a separate typedef inside the implementation file, and ensure that they are synchronized.
You can ensure that the types are the same with a small bit of metaprogramming, with a same_type<T,U> template that will provide a true value if the two types are the same and false otherwise. A static assert will trigger an error if the typedef changes in only one place
Back to simple again: provide the typedef or use the type directly without the static assert.
You are calling a function (this should not be a template as in your code) and passing a reference. If the typedef changes in the class, the call will fail and the compiler will tell you.
I would go for the last option, while it may look a little rough and less delicate than the others, the fact is that this is only an implementation detail that is not used by others, you are under full control of the code and well, simple is better.
EDIT, after the comment.
I started writing this as a comment, but it became too long, so I am adding it to the answer.
There is nothing wrong in that solution by itself, other than you are making a function generic unnecessarily and some error messages in the future might not be as simple as they could be with a non-generic signature. Note that the template will not expose the typedef (as the question title suggests) but rather it will make the compiler infer the type at the place of call.
If you change the typedef, instead of getting an error saying that the arguments to helperFn cannot be matched against the existing function, the type will be inferred and the function matched, but you will get an error deeper in helperFn if you use a property of the type that is no longer present. Or worse, you might not even get an error if it is the semantics of the type that have changed.
Consider that the typedef is of a std::list<X>, and that in the function you are iterating over it with this simple correct for loop:
for (typename T::iterator it=x.begin(), end=x.end(); it != end; ) {
if ( condition(*it) )
it = x.erase(it);
else
++it;
}
Can you catch the effect that changing the typedef to std::vector<X> will have? The compiler cannot even if the code is now incorrect. Whether writing the for loop like that is a good idea, or why is it not just using the erase-remove idiom are different issues (as a matter of fact the previous loop is arguably better than erase-remove for a list), the concrete situation is that the semantics have changed, and because the type is syntactically compatible with the previous one the compiler will not notice that the code is wrong, it will not point you to that function and chances are that you will not review/rewrite it.
I guess this is the idea of generic programming - do stuff with a part of Foo without knowing its type.
A more "traditional" (strongly-typed, boring, readable, code-duplicating - you name it) way would be to mention the type explicitly:
int helperFn(const std::blahblah& foopart, int index)
{
...
return foopart.fn(index);
}
In C# 4.0, you can use the "dynamic" keyword as a placeholder for a type that is not known until runtime. There are certain corner cases where this is extremely useful behavior. Is it possible to emulate anything like this in C++, possibly using C++0x features or RTTI?
Not really. The closest you can get is a void *, but you still need to cast it to an appropriate type before you can use it.
Update:
Trying to build a duck-typed DSL that compiles to C++, basically.
You can go about this in at least two ways:
Union-based variant
struct MyType {
enum { NUMBER, STRING /* etc */ } type;
union {
double number;
string str;
};
};
Polymorphic class heirarchy
class MyType {
public:
/* define pure virtual operations common to all types */
};
class MyNumber : public MyType {
private:
double number;
public:
/* implement operations for this type */
};
C#'s dynamic feature is highly dependant on .NET's built-in reflection capabilities. As standard C++ offers next to no reflection support, there's no way you can get a similar behavior. RTTI will allow you to safely downcast pointers but that's pretty much it. You're still quite far to being able to enumerate fields and methods and invoke them dynamically.
As others already said this isn't possible in the general case but I think it would be informative to see why not.
There are two levels to the problem, the syntactic level and the semantic level.
On the syntactic level you have the following code:
dynamic d = /* something */;
d.Foo(bar); // Foo is unknown at compile time
In .NET dynamic is a compiler feature, what it does is instead of generating a function call it creates a call site which contains the function name and types of parameters (for overloading). This means that if you want to support dynamic you have to modify the compiler. It's true that template meta programming allows doing similar stuff but TMP is by its nature done at compile time and therefore won't be up to the job of supporting runtime invocation.
If you're not anal about the syntax then you may be able to support something like this:
dynamic d = /* something */;
d.invoke("Foo", bar);
On the semantic level
As #Trillian (cool user name BTW) said, dynamic relies on reflection, this isn't strictly true, you can specify how dynamic is implemented, and the default for CLR types is reflection, so the type that bound to a dynamic variable must support some sort of runtime inspection (e.g. COM's IDispatch). This isn't true for the general case in C++ but if you can narrow your support only to types that support (a known) type of inspection you can implement dynamic in C++ (sans the syntax as mentioned above).
It's not possible. Object sizes need to be known at compile-time, so the stack pointer can move by the appropriate number of bytes. If you don't declare the type, then the compiler won't know the size. C# gets around this problem by making all objects pointers.
This example on github provides one possible implementation, depending on your function complexity.
template <typename X, typename Y>
auto add(X x, Y y) -> decltype(x + y) {
return x + y;
}
add(1, 2); // == 3
add(1, 2.0); // == 3.0
add(1.5, 1.5); // == 3.0
I can't think of a possible code path where the type of a value is actually unknown all the way until run-time. Even if you are linking two modules together (dynamically, at run time), both are already compiled, and the types that they can return are also fully determined, and in fact encoded into the mangled names of the symbols the library exposes.
You can, however, defer knowledge of types until the code must actually be compiled. In C++0x, there's the auto keyword, which provides type inference from the expression used to initialize the variable, and in current C++, you can use templates, like so:
template<typename T>
T square(const T& someArg){
return T*T;
}
Edit: based on your comment on your question, You probably don't have a situation where the type is unknown. What's more likely is that the type is limited to one of a few (predefined) types. for that, you can use a union type, preferably using boost::variant
Before this is marked as duplicate, I'm aware of this question, but in my case we are talking about const containers.
I have 2 classes:
class Base { };
class Derived : public Base { };
And a function:
void register_objects(const std::set<Base*> &objects) {}
I would like to invoke this function as:
std::set<Derived*> objs;
register_objects(objs);
The compiler does not accept this. Why not? The set is not modifiable so there is no risk of non-Derived objects being inserted into it. How can I do this in the best way?
Edit:
I understand that now the compiler works in a way that set<Base*> and set<Derived*> are totally unrelated and therefor the function signature is not found. My question now however is: why does the compiler work like this? Would there be any objections to not see const set<Derived*> as derivative of const set<Base*>
The reason the compiler doesn't accept this is that the standard tells it not to.
The reason the standard tells it not to, is that the committee did not what to introduce a rule that const MyTemplate<Derived*> is a related type to const MyTemplate<Base*> even though the non-const types are not related. And they certainly didn't want a special rule for std::set, since in general the language does not make special cases for library classes.
The reason the standards committee didn't want to make those types related, is that MyTemplate might not have the semantics of a container. Consider:
template <typename T>
struct MyTemplate {
T *ptr;
};
template<>
struct MyTemplate<Derived*> {
int a;
void foo();
};
template<>
struct MyTemplate<Base*> {
std::set<double> b;
void bar();
};
Then what does it even mean to pass a const MyTemplate<Derived*> as a const MyTemplate<Base*>? The two classes have no member functions in common, and aren't layout-compatible. You'd need a conversion operator between the two, or the compiler would have no idea what to do whether they're const or not. But the way templates are defined in the standard, the compiler has no idea what to do even without the template specializations.
std::set itself could provide a conversion operator, but that would just have to make a copy(*), which you can do yourself easily enough. If there were such a thing as a std::immutable_set, then I think it would be possible to implement that such that a std::immutable_set<Base*> could be constructed from a std::immutable_set<Derived*> just by pointing to the same pImpl. Even so, strange things would happen if you had non-virtual operators overloaded in the derived class - the base container would call the base version, so the conversion might de-order the set if it had a non-default comparator that did anything with the objects themselves instead of their addresses. So the conversion would come with heavy caveats. But anyway, there isn't an immutable_set, and const is not the same thing as immutable.
Also, suppose that Derived is related to Base by virtual or multiple inheritance. Then you can't just reinterpret the address of a Derived as the address of a Base: in most implementations the implicit conversion changes the address. It follows that you can't just batch-convert a structure containing Derived* as a structure containing Base* without copying the structure. But the C++ standard actually allows this to happen for any non-POD class, not just with multiple inheritance. And Derived is non-POD, since it has a base class. So in order to support this change to std::set, the fundamentals of inheritance and struct layout would have to be altered. It's a basic limitation of the C++ language that standard containers cannot be re-interpreted in the way you want, and I'm not aware of any tricks that could make them so without reducing efficiency or portability or both. It's frustrating, but this stuff is difficult.
Since your code is passing a set by value anyway, you could just make that copy:
std::set<Derived*> objs;
register_objects(std::set<Base*>(objs.begin(), objs.end());
[Edit: you've changed your code sample not to pass by value. My code still works, and afaik is the best you can do other than refactoring the calling code to use a std::set<Base*> in the first place.]
Writing a wrapper for std::set<Base*> that ensures all elements are Derived*, the way Java generics work, is easier than arranging for the conversion you want to be efficient. So you could do something like:
template<typename T, typename U>
struct MySetWrapper {
// Requirement: std::less is consistent. The default probably is,
// but for all we know there are specializations which aren't.
// User beware.
std::set<T> content;
void insert(U value) { content.insert(value); }
// might need a lot more methods, and for the above to return the right
// type, depending how else objs is used.
};
MySetWrapper<Base*,Derived*> objs;
// insert lots of values
register_objects(objs.content);
(*) Actually, I guess it could copy-on-write, which in the case of a const parameter used in the typical way would mean it never needs to do the copy. But copy-on-write is a bit discredited within STL implementations, and even if it wasn't I doubt the committee would want to mandate such a heavyweight implementation detail.
If your register_objects function receives an argument, it can put/expect any Base subclass in there. That's what it's signature sais.
It's a violation of the Liskov substitution principle.
This particular problem is also referred to as Covariance. In this case, where your function argument is a constant container, it could be made to work. In case the argument container is mutable, it can't work.
Take a look here first: Is array of derived same as array of base. In your case set of derived is a totally different container from set of base and since there is no implicit conversion operator is available to convert between them , compiler is giving an error.
std::set<Base*> and std::set<Derived*> are basically two different objects. Though the Base and Derived classes are linked via inheritance, at compiler template instantiation level they are two different instantiation(of set).
Firstly, It seems a bit odd that you aren't passing by reference ...
Secondly, as mentioned in the other post, you would be better off creating the passed-in set as a std::set< Base* > and then newing a Derived class in for each set member.
Your problem surely arises from the fact that the 2 types are completely different. std::set< Derived* > is in no way inherited from std::set< Base* > as far as the compiler is concerned. They are simply 2 different types of set ...
Well, as stated in the question you mention, set<Base*> and set<Derived*> are different objects. Your register_objects() function takes a set<Base*> object. So the compiler do not know about any register_objects() that takes set<Derived*>. The constness of the parameter does not change anything. Solutions stated in the quoted question seem the best things you can do. Depends on what you need to do ...
As you are aware, the two classes are quite similar once you remove the non-const operations. However, in C++ inheritance is a property of types, whereas const is a mere qualifier on top of types. That means that you can't properly state that const X derives from const Y, even when X derives from Y.
Furthermore, if X does not inherit from Y, that applies to all cv-qualified variants of X and Y as well. This extends to std::set instantiations. Since std::set<Foo> does not inherit from std::set<bar>, std::set<Foo> const does not inherit from std::set<bar> const either.
You are quite right that this is logically allowable, but it would require further language features. They are available in C# 4.0, if you're interested in seeing another language's way of doing it. See here: http://community.bartdesmet.net/blogs/bart/archive/2009/04/13/c-4-0-feature-focus-part-4-generic-co-and-contra-variance-for-delegate-and-interface-types.aspx
Didn't see it linked yet, so here's a bullet point in the C++ FAQ Lite related to this:
http://www.parashift.com/c++-faq-lite/proper-inheritance.html#faq-21.3
I think their Bag-of-Apples != Bag-of-Fruit analogy suits the question.