Any way to cast with class operator only? - c++

Kind of a random question...
What I'm looking for is a way to express a cast operation which uses a defined operator of the class instance I'm casting from, and generates a compile-time error if there is not a defined cast operator for the type. So, for example, what I'm looking for is something like:
template< typename RESULT_TYPE, typename INPUT_TYPE >
RESULT_TYPE operator_cast( const INPUT_TYPE& tValue )
{
return tValue.operator RESULT_TYPE();
}
// Should work...
CString sString;
LPCTSTR pcszString = operator_cast< LPCTSTR >( sString );
// Should fail...
int iValue = 42;
DWORD dwValue = operator_cast< DWORD >( iValue );
Interesting side-note: The above code crashes the VS2005 C++ compiler, and doesn't compile correctly in the VS2008 C++ compiler due to what I'm guessing is a compiler bug, but hopefully demonstrates the idea.
Anybody know of any way to achieve this effect?
Edit: More rationale, to explain why you might use this. Say you have a wrapper class which is supposed to encapsulate or abstract a type, and you're casting it to the encapsulated type. You could use static_cast<>, but that might work when you wanted it to fail (ie: the compiler chooses an operator which is allowed to convert to the type you asked for, when you wanted a failure because that operator is not present).
Admittedly it's an uncommon case, but it's annoying that I can't express exactly what I want the compiler to do in an encapsulated function... hence the question here.

The code you posted works with the Cameau compiler (which is usually a good indication that it's valid C++).
As you know a valid cast consists of no more than one user defined cast, so a possible solution I was thinking of was adding another user defined cast by defining a new type in the cast template and having a static assert that no cast is available from the new type to the result type (using boost is_convertible), however this doesn't distinguish between cast operators and cast constructors (ctor with one argument) and alows additional casts to take place (e.g. void* to bool). I'm not sure if making a distinction between cast operators and cast constructors is the the correct thing to do but that's what the question states.
After a couple of days mulling this over it hit me, you can simply take the address of the cast operator. This is slightly easier said than done due to C++'s hairy pointer to member syntax (it took me way longer than expected to get it right). I don't know if this works on VS2008, I only checked it on Cameau.
template< typename Res, typename T>
Res operator_cast( const T& t )
{
typedef Res (T::*cast_op_t)() const;
cast_op_t cast_op = &T::operator Res;
return (t.*cast_op)();
}
Edit: I got a chance to test it on VS2005 and VS2008. My findings differ from the original poster's.
On VS2008 the original version seems to work fine (as does mine).
On VS2005 the original version only crashes the compiler when casting from a built in type (e.g. casting int to int) after providing a compilation error which doesn't seem so bad too me and my version seems to works in all cases.

Using a converting constructor marked explicit is how you would prevent the compiler from allowing implicitly converted types from initializing your wrapper class.

As template-related compiler error messages are usually a complete pain to unravel, if you don't mind specifying each conversion you can get the compiler to emit a more instructive message in the fail case by providing a default template definition too. This uses the fact that the compiler will only attempt to compile code in templates that is actually invoked.
#include <string>
// Class to trigger compiler warning
class NO_OPERATOR_CONVERSION_AVAILABLE
{
private:
NO_OPERATOR_CONVERSION_AVAILABLE(){};
};
// Default template definition to cause compiler error
template<typename T1, typename T2> T1 operator_cast(const T2&)
{
NO_OPERATOR_CONVERSION_AVAILABLE a;
return T1();
}
// Template specialisation
template<> std::string operator_cast(const std::string &x)
{
return x;
}

sounds like you want template specialization, something like this would do:
/* general template */
template<typename T1, typename T2> T1 operator_cast(const T2 &x);
/* do this for each valid cast */
template<> LPCTSTR operator_cast(const CString &x) { return (LPCTSTR)x; }
EDIT: As noted in another post, you can put something in the general version to give you a more useful error message if an unsupported cast is performed.

Related

Difference between boost optional and std::experimental optional assignment

Usually when a function returns boost::optional I've seen a lot of people returning an empty brace {} to designate an empty value, that works fine and is shorter than returning boost::none.
I tried to do something similar to empty a boost::optional<int>, but when calling the copy assignment operator (or most probably the move assignment op) with an empty brace in the right side, the empty brace is converted to an int and then that value is assigned to the optional, so I end up with the variable set to 0 and not an empty value as I was expecting. Here's an example https://godbolt.org/g/HiF92v, if I try the same with std::experimental::optional I get the result I'm expecting (just replace with std::experimental::optional in the example and you will see that the instruction becomes mov eax, eax).
Also if I try with a different template argument for the boost optional (a non integer type) some compilers compile (with the behavior I'm expecting, an example here http://cpp.sh/5j7n) and others don't. So even for the same lib the behavior is different according to the template arg.
I'd like to understand what is going on here, I know it has something to do with the fact that I'm using a C++14 feature for a library that doesn't consider that into the design. I read the boost/optional header but I got lost in the details, I also tried to study the compiled code without inlining with a similar result.
I'm using gcc 4.9.2 with -std=c++14 and boost 1.57.
btw: I known I should have used boost::optional::reset or boost::none, but I was trying to be consistent with the semantics in the rest of the code base.
To understand what is going on, consider this example first:
void fun(int) { puts("f int"); }
void fun(double) { puts("f double"); }
int main() {
fun({}); // error
}
This results in a compiler error, because the overload resolution is inconclusive: double and int fit equally well. But, if a non-scalar type comes into play, the situation is different:
struct Wrap{};
void fun(int) { puts("f(int)"); }
void fun(Wrap) { puts("f(Wrap)"); }
int main() {
fun({}); // ok: f(int) selected
}
This is because a scalar is a better match. If, for some reason, I want the same two overloads but at the same time I would like fun({}) to select overload fun(Wrap), I can tweak the definitions a bit:
template <typename T>
std::enable_if_t<std::is_same<int, std::decay_t<T>>::value>
fun(T) { puts("f int"); }
void fun(Wrap) { puts("f(Wrap)"); }
That is, fun(Wrap) remains unchanged, but the first overload is now a template that takes any T. But with enable_if we constrain it, so that it only works with type int. So, this is quite an 'artificial' template, but it does the job. If I call:
fun(0); // picks fun(T)
The artificial template gets selected. But if I type:
fun({}); // picks fun(Wrap)
The artificial template is still a template, so it is never considered in type deduction in this case, and the only visible overload is fun(Wrap), so it gets selected.
The same trick is employed in std::optional<T>: it does not have an assignment from T. Instead it has a similar artificial assignment template that takes any U, but is later constrained, so that T == U. You can see it in the reference implementation here.
boost::optional<T> has been implemented before C++11, unaware of this 'reset idiom'. Therefore it has a normal assignment from T, and in cases where T happens to be a scalar this assignment from T is preferred. Hence the difference.
Given all that, I think that Boost.Optional has a bug that it does something opposite than std::optional. Even if it is not implementable in Boost.Optional, it should at least fail to compile, in order to avoid run-time surprises.

How is std::is_empty<T> implemented in VS2015 (or any compiler)?

My current question has been inspired by attempting to understand how std::unique_ptr<T, D> utilizes template mechanics to instantiate a template class the size of a T* when D (the deleter type) is a lambda function type, but a larger size when D is a function pointer type (since space needs to be allocated in the unique_ptr instance to store the function pointer).
Looking through the VS2015 source code, I find that std::unique_ptr derives from std::_Unique_ptr_base, which in turn declares a data member of type _Compressed_pair<class _Ty1, class _Ty2, bool = is_empty<_Ty1>::value && !is_final<_Ty1>::value>. The type _Ty1 in this latter context is the type of the deleter, D, that is the second unique_ptr template parameter noted in the previous paragraph; i.e., the motivation behind this question is that I am contrasting _Ty1 being a lambda type, vs. _Ty1 being a function pointer type. (In fact, the default value of the bool is being utilized.)
I recognize that is_empty<_Ty1>::value is true when _Ty1 is an instance of a lambda type (when the lambda has no capture variables and therefore has a 0 size); but that it is false when _Ty1 is a function pointer type.
This led me to pursue how std::is_empty is defined.
Ugh!
What follows is the complete implementation of std::is_empty that I can find in the VS2015 C++ library source code.
In the file type_traits is this:
// TEMPLATE CLASS is_empty
template<class _Ty>
struct is_empty _IS_EMPTY(_Ty)
{ // determine whether _Ty is an empty class
};
... and the macro _IS_EMPTY is defined in the same file:
#define _IS_EMPTY(_Ty) \
: _Cat_base<__is_empty(_Ty)>
... and at this point my luck runs dry, because I cannot find the definition of __is_empty anywhere. I have GREPped through the entire VS2015 installation directory (which includes, I think, all of the C++ library source code, in - though perhaps I'm mistaken).
I like to understand C++ internals when I want to. But ... I'm stuck on this one, and plenty of googling did not reveal the answer (though I have seen reference to intrinsics), and my digging has not ... discovered any source code.
Can someone enlighten this situation? How is std::is_empty<T> actually implemented in VS2015, or, for that matter, any other compiler?
Looks as if MSVC++ provides an intrinsic __isempty(T) rather than dealing with a library-level implementation. Since the argument type T passed to std::is_empty<T> can be final, I don't think there can be a safe library implementation and compiler help may be needed.
The only way to determine if a type T is empty in a library I can think of is this (the specialization deals with non-class types for which std::is_empty<T> is not true):
template <bool, typename T>
struct is_empty_aux: T { unsigned long long dummy; };
template <typename T>
struct is_empty_aux<false, T> { unsigned long long dummy[2]; };
template <typename T>
struct is_empty:
std::integral_constant<bool,
sizeof(is_empty_aux<std::is_class<T>::value, T>)
== sizeof(unsigned long long)> {
};
However, if T is final the inheritance in is_empty_aux is illegal. While the case of a final class can be detected using std::is_final<T> I don't see a way to determine whether its objects are empty. Thus, using a compiler intrinsic may be necessary. Compiler intrinsics are certainly necessary for some of the other type traits anyway. Compiler intrinsics are declarations/definitions somehow magically provided by the compiler: they are normally neither explicitly declared nor defined. The compiler has the necessary knowledge about types and exposing this knowledge via intrinsics is a reasonable approach.
Also ran across this question and took a look at the gcc 4.8 headers in Ubuntu 14.04. In fact there are a family of them, like __is_empty, __is_pod, __is_polymorphic, etc, used in this way
// /usr/include/c++/4.8/type_traits:516
template<typename _Tp>
struct is_empty
: public integral_constant<bool, __is_empty(_Tp)>
{};
They seem to work without including any C++ headers. I've tried g++ and clang++ to compile this code
#include <stdio.h>
struct X {};
int main()
{
printf("%d %d %d\n", __is_empty(X), __is_enum(X), __is_class(X));
return 0;
}
What I feel uncommon is that they look like functions but actually take a type as argument, instead of an instance (not work if you try X x; __is_empty(x);).

Ensure argument is an output stream for the console

I'm trying to make a stream manipulator for colour for use with output to the console. It works, changing the colour of text and the background:
std::cout << ConColor::Color::FgBlue << 123 << "abc"; //text is blue, sticky
The problem is with the signature:
std::ostream &FgBlue(std::ostream &);
This signature allows for derived classes, such as std::ostringstream as well, but there is no way to change the colour of a string stream. The function would change the colour of the console regardless if it was called with such an argument.
Therefore, I want to ensure the argument is something along the lines of std::cout, std::wcout, etc. I would prefer it be general in the case that more std::ostream objects are added in a future standard.
I tried many things involving std::is_same and std::is_base_of, when the former wouldn't work, just to eventually realize that it was pointless because any argument type inheriting from std::basic_ostream<> will be casted to the type I'm comparing against when passed to the function, giving false positives.
This eventually led me to my answer below (variadic template template arguments? Wow, that's a mouthful!) There are a couple problems, however:
The compiler must support variadic templates. I would prefer the solution work on MSVC.
The compiler gives cryptic errors in the case that a derived class with a different number of template arguments (such as std::ostringstream, which has 3 instead of 2) is used, as it doesn't get past the function signature.
It's possible to redirect stdout, say, to a file, so even if the argument is std::cout, the same thing as the stringstream case happens.
I encourage people to post any other solutions, hopefully better than mine, and really hopefully something that works with at least VS11.
Here's a trait for detecting std::basic_ostream instantiations:
template<typename T> struct is_basic_ostream {
template<typename U, typename V>
static char (&impl(std::basic_ostream<U, V> *))[
std::is_same<T, std::basic_ostream<U, V>>::value ? 2 : 1];
static char impl(...);
static constexpr bool value = sizeof(impl((T *)0)) == 2;
};
Use as:
template<typename T>
void foo(T &) {
static_assert(is_basic_ostream<T>::value,
"Argument must be of type std::basic_ostream<T, U>.");
}
We use template argument deduction to infer the template parameters on the (non-proper) basic_ostream base class, if any. As a more general solution, replacing U and V with a single variadic parameter would allow writing a generic is_instantiation_of trait on compilers that support variadic template parameters.
To detect whether stdout is piped to a file (which can only be detected at runtime, of course) use isatty; see how to use isatty() on cout, or can I assume that cout == file descriptor 1?
This is what I came up with after a lot of trial:
template<template<typename...> class T, typename... U>
void foo(T<U...> &os) {
static_assert(
std::is_same<
std::basic_ostream<U...>,
typename std::remove_reference<decltype(os)>::type
>::value,
"Argument must be of type std::basic_ostream<T, U>."
);
//...
}
Source code containing each of the below tests can be found here.
Source code replacing the types with similar self-made ones that are more explicit and offer more freedom (e.g., instantiation), which might be more useful for testing, can be found here.
Passing in std::cout and std::wcout makes it compile fine.
Passing in an instance of std::ostringstream causes it to complain about the number of template arguments.
Passing in an instance of std::fstream, which has the same number of template parameters, causes the static assertion to fail.
Passing in a self-made 2-parameter template class causes the static assertion to fail.
Please feel free to improve upon this any way you can.

Is there a way to use SFINAE to determine if a call to a templated function would fail due to the types provided?

I have a templated class that I am using to provide a method that will use boost::lexical_cast to cast its std::string parameters to the type specified in the template, only if the lexical cast is possible. Currently to check if it's possible I'm simply checking to see if operator>> is defined for the type in question. Here is a contrived example that basically illustrates what I'm doing:
template <typename ArgType, class Enable = void>
MyHelperClass
{
void Foo (ArgType arg&, std::string strArg) { } // not castable; do nothing
};
template <typename ArgType>
MyHelperClass<ArgType, boost::enable_if<boost::has_right_shift<std::istream, ArgType> >::type>
{
void Foo (ArgType arg&, std::string strArg) {
arg = boost::lexical_cast<ArgType>(strArg); // cast string arg to ArgType
}
};
So far this works fine for my code: all of the types that would fail a lexical cast end up with the first version and all others end up with the second, at least for the types my code is using this on. What I'm worried about is that I'm basically making the assumption that as long as the target type is InputStreamable then lexical_cast will not fail. The boost documentation for lexical_cast outlines some other requirements, which I should probably be checking as well but rather than creating a complex enable-if and use mpl::and_ to string together a bunch of these conditions, I was wondering: is there a way to use SFINAE to just test directly whether that call to lexical_cast would fail for the types given, and match the specialized template only if it wouldn't fail?
I've only ever seen examples for testing the existence of a function or operator, but never to test if a call to a templated function with a given type would produce an error.
I'm afraid not. Because lexical_cast is defined for all T, SFINAE won't help you. The fact that the body of lexical_cast() will fail to compile for certain types does not cause a substitution failure. The best you can do is to try to predict the conditions that will cause the body to fail, as you have already been doing.

Why can't auto be used as a template type parameter?

I've been playing around with C++0x's auto keyword and tried the following.
std::unique_ptr<auto> ptr(new int(0));
I tried compiling it with g++ 4.4.5 and got
error: invalid use of auto
Judging by eye, auto can easily be inferred to int.
My guess is the type inference and the template engine don't talk to each other. Otherwise, the template engine would know to instantiate the template class with int as the type parameter.
Another guess is from the standard, I see this.
A member shall not be declared with auto, extern or register storage class.
But I thought that was the auto as in local variables, not as in auto used to deduce types.
And my last guess is that the compiler thinks this is an auto storage class, not auto for type deduction.
Is there a reason behind this stated in the standard?
That's because it has to determine the class on which to call a constructor before determining what to do with its arguments. If you make the constructor a template, it'll just work like any other template function - auto-deducing arguments.
#dascandy has correctly identified what's wrong with your code. I'll try to provide some rationale:
You're expecting the compiler to infer unique_ptr<int> because the argument is an int*, and unique_ptr<int> has a constructor which accepts int*. For a moment let's ignore the fact that we're using std::unique_ptr, and just talk about a template class we wrote (and can specialize).
Why should the compiler infer unique_ptr<int>? The argument isn't int, it's int*. Why shouldn't it guess unique_ptr<int*>? Of course that would result in a compiler error, since unique_ptr<int*>'s constructor won't accept an int*. Unless I add a specialization:
template<>
class unique_ptr<int*>
{
public:
unique_ptr(int*) {}
};
Now unique_ptr<int*> would compile. How should the compiler know which to choose, unique_ptr<int> or unique_ptr<int*>? What if I add another specialization?
template<>
class unique_ptr<double>
{
public:
unique_ptr(int*) {}
};
The compiler now has three options to choose from, and it has to instantiate the template with every possible argument in order to find them. Clearly this is not feasible, especially with multiple template arguments and template recursion.
What you can do, is make a factory function which connects the inferred type to exactly one template instance:
template<typename T>
std::unique_ptr<T> make_unique(T* arg) { return arg; }
(of course, this won't work because unique_ptr cannot be copied. But the idea is valid, and used in e.g.make_shared and make_pair.)
Some examples of extreme ugliness:
One could argue that unique_ptr<shared_ptr<int>> is a valid match for this code.
Or how about:
template<typename T>
class unique_ptr
{
public:
explicit unique_ptr(T* arg);
unique_ptr(int*, enable_if<(sizeof(T) > 16)>::type* = 0);
};
Just want to add that a solution already exists for most cases:
template <typename T>
std::unique_ptr<T> unique_ptr_auto(T* ptr)
{
// fails to handle std::unique_ptr<T[]>, not deducible from pointer
return std::unique_ptr<T>(ptr);
}
auto ptr = unique_ptr_auto(new int(0));
A bit more verbose, obviously, but you get the idea. These "generator functions" are quite common.
This (or similar) was proposed for the Standard. The proposed functionality looked something like:
std::vector<int> GetMahVector();
std::vector<auto> var = GetMahVector();
However, it was rejected. Why it was rejected, well, you'd have to dig up the relevant Standard process documents, if possible.