identity<T> wrapper in an overload function signature disables overload - c++

I hava overloaded stream operator << for a new template type X<T> and that works. But if I wrap that type with the identity function identity<X<T>>::type the code breaks.
I tried gcc 4.6.2 / gcc 4.8.1 / clang 3.3
Any hint?
#include <iostream>
template <typename T>
struct ebenso // because I could not find std::identity, any hint?
{
typedef T type;
};
template <typename T>
struct X
{
T value;
};
template<typename T>
inline std::ostream &
operator << (std::ostream& stream, typename ebenso< X<T> >::type const & x)
{
return stream << x.value << std::endl;
}
int main ()
{
X<int> x;
x.value = 7;
std::cout << x << std::endl; // The overload is not found
}

Related

Differentiate between user type and primitives

I'm trying to differentiate between user types and primitive types in a variadic template.
I have tried overloading binary operator, but that only says that there's no fitting overload for 'user types'...
template <typename T>
void PrintParams(T t)
{
if (IsAUserType)
std::cout << typeid(t).name();
else
std::cout << t;
}
template <typename First, typename... Rest>
void PrintParams(First first, Rest... rest)
{
if (IsAUserType)
std::cout << typeid(first).name();
else
std::cout << first;
PrintParams(rest...);
}
// If you know what to do with this, then that would also be very helpful...
//Overload << operator for user types
//template <typename T>
//friend std::ostream& operator<< (std::ostream& os, T t)
//{
//
//if (std::is_fundamental<t>::value)
//std::clog << t;
//else
//std::clog << typeid(t).name();
//}
expected result for input like (class test, 3.4, "string") would be
"test3.4string"
You could split your single argument function up in two and use SFINAE to enable the correct one depending on if the argument is a fundamental type or not:
template<typename T, typename std::enable_if<std::is_fundamental<T>::value, int>::type = 0>
void PrintParams(T t) {
std::cout << t;
}
template<typename T, typename std::enable_if<!std::is_fundamental<T>::value, int>::type = 0>
void PrintParams(T t) {
std::cout << typeid(t).name();
}
template<typename First, typename... Rest>
void PrintParams(First first, Rest... rest) {
PrintParams(first); // ... and call the single argument version here
std::cout << ",";
PrintParams(rest...);
}
Another way would be to check if the type supports streaming using operator<< instead of checking that it's a fundamental type. That would make streaming work for classes (like std::string and user defined ones too).
#include <iostream>
#include <type_traits>
#include <typeinfo>
#include <utility>
// SFINAE support
namespace detail {
template<class>
struct sfinae_true : std::true_type {};
template<class S, class T>
static auto test_lshift(int)
-> sfinae_true<decltype(std::declval<S>() << std::declval<T>())>;
template<class S, class T>
static auto test_lshift(long) -> std::false_type;
} // namespace detail
template<class T>
struct has_ostream : decltype(detail::test_lshift<std::ostream, T>(0)) {};
// using the SFINAE support stuff
template<typename T, typename std::enable_if<has_ostream<T>::value, int>::type = 0>
void PrintParams(const T& t) {
std::cout << "Type: " << typeid(t).name() << "\n"
<< " supports operator<< Value = " << t << "\n";
}
template<typename T, typename std::enable_if<!has_ostream<T>::value, int>::type = 0>
void PrintParams(const T& t) {
std::cout << "Type: " << typeid(t).name() << "\n"
<< " does NOT support operator<<\n";
}
template<typename First, typename... Rest>
void PrintParams(First first, Rest... rest) {
PrintParams(first);
PrintParams(rest...);
}
// example classes
class Foo { // will not support streaming
int x = 5;
};
class Bar { // this should support streaming
int x = 10;
friend std::ostream& operator<<(std::ostream&, const Bar&);
};
std::ostream& operator<<(std::ostream& os, const Bar& b) {
return os << b.x;
}
// testing
int main() {
int i = 2;
Foo f;
Bar b;
std::string s = "Hello world";
PrintParams(i, f, b, s);
}
Possible output:
Type: i
supports operator<< Value = 2
Type: 3Foo
does NOT support operator<<
Type: 3Bar
supports operator<< Value = 10
Type: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
supports operator<< Value = Hello world
I think std::is_class can replace your IsAUserType.
https://en.cppreference.com/w/cpp/types/is_class
Primitive data types include integer , character , void , float etc..which are defined already inside the language i.e , user can use these data types without defining them inside the language.
User defined data types are the data types which user have to define while or before using them.

Is there way out of this ambiguity?

Consider this (rather) simple example:
#include <iostream>
struct Out {
int value;
};
template<class Sink> decltype(auto) operator<<(Sink &&s, Out const &out) {
return out.value > 0? s << out.value : s;
}
struct In {
std::ostream &sink;
template<typename T> In &operator<<(T const &t) {
return sink << t, *this;
}
};
int main() {
In in{std::cout};
in << (1 << Out{3}) << '\n'; // Ok
in << Out{42} << '\n';
// error: use of overloaded operator '<<' is ambiguous
// (with operand types 'In' and 'Out')
}
Can such an ambiguity be addressed? We have two classes, each one defines such an operator overload to forward it to its internal type (classes are designed independently by two different people, and another person tries to use them in the same application.) I don't see a way this could be reformulated in terms of other operators, say, it's no use here to give up on A's friend operator<< and try to convert A to int; and to use some kind of complicated SFINAE to rule out some overloads still doesn't look helpful.
You might create additional overloads which would be the better match:
decltype(auto) operator<<(In& in, Out const &out) {
return in.operator<<(out);
}
decltype(auto) operator<<(In&& in, Out const &out) {
return in.operator<<(out);
}
Some semi-oldschool SFINAE seemingly does the trick, in the sense that it is now accepted by both gcc and clang (and they both print "8" and "42" equally):
#include <iostream>
#include <utility>
template<typename S, typename T> class can_shl {
using Left = char;
struct Right { char c[2]; };
template<typename U> static constexpr decltype(
std::declval<S>() << std::declval<U>(), Left{})
has_it(U &&);
static constexpr Right has_it(...);
public:
static constexpr bool value = sizeof(has_it(std::declval<T>())) == 1;
};
struct Out {
int value;
};
template<class Sink> auto operator<<(Sink &&s, Out const &out)
-> std::enable_if_t<!can_shl<Sink, Out>::value, decltype(out.value > 0? s << out.value : s)>
{
return out.value > 0? s << out.value : s;
}
struct In {
std::ostream &sink;
template<typename T> In &operator<<(T const &t) {
return sink << t, *this;
}
};
int main() {
In in{std::cout};
in << (1 << Out{3}) << '\n'; // Ok
in << Out{42} << '\n';
}
Personally I don't feel quite confident with that "only allow this in case it does not compile on its own" approach (is this perchance a (static) UB? what would I say if I were a C++ standard?)

Fallback to to_string() when operator<<() fails

I've seen types that have corresponding to_string() function, but haven't overloaded operator<<(). So, when inserting to stream, one has to << to_string(x) which is verbose. I'm wondering whether it's possible to write a generic function that users operator<<() if supported and falls back to << to_string() if not.
SFINAE is overkill, use ADL.
The trick is to make sure that an operator<< is available, not necessarily the one supplied by the type definition:
namespace helper {
template<typename T> std::ostream& operator<<(std::ostream& os, T const& t)
{
return os << to_string(t);
}
}
using helper::operator<<;
std::cout << myFoo;
This trick is commonly used in generic code which needs to choose between std::swap<T> and a specialized Foo::swap(Foo::Bar&, Foo::Bar&).
Try
template <typename T>
void print_out(T t) {
print_out_impl(std::cout, t, 0);
}
template <typename OS, typename T>
void print_out_impl(OS& o, T t,
typename std::decay<decltype(
std::declval<OS&>() << std::declval<T>()
)>::type*) {
o << t;
}
template <typename OS, typename T>
void print_out_impl(OS& o, T t, ...) {
o << t.to_string();
}
LIVE
Yes, it is possible.
#include <iostream>
#include <sstream>
#include <string>
#include <type_traits>
struct streamy
{
};
std::ostream&
operator<<(std::ostream& os, const streamy& obj)
{
return os << "streamy [" << static_cast<const void *>(&obj) << "]";
}
struct stringy
{
};
std::string
to_string(const stringy& obj)
{
auto oss = std::ostringstream {};
oss << "stringy [" << static_cast<const void *>(&obj) << "]";
return oss.str();
}
template <typename T>
std::enable_if_t
<
std::is_same
<
std::string,
decltype(to_string(std::declval<const T&>()))
>::value,
std::ostream
>&
operator<<(std::ostream& os, const T& obj)
{
return os << to_string(obj);
}
int
main()
{
std::cout << streamy {} << '\n';
std::cout << stringy {} << '\n';
}
The generic operator<< will only be available if the expression to_string(obj) is well-typed for obj a const T& and has a result of type std::string. As you have already conjectured in your comment, this is indeed SFINAE at work. If the decltype expression is not well-formed, we will get a substitution failure and the overload will disappear.
However, this will likely get you into troubles with ambiguous overloads. At the very least, put your fallback operator<< into its own namespace and only drag it in locally via a using declaration when needed. I think you will be better off writing a named function that does the same thing.
namespace detail
{
enum class out_methods { directly, to_string, member_str, not_at_all };
template <out_methods> struct tag {};
template <typename T>
void
out(std::ostream& os, const T& arg, const tag<out_methods::directly>)
{
os << arg;
}
template <typename T>
void
out(std::ostream& os, const T& arg, const tag<out_methods::to_string>)
{
os << to_string(arg);
}
template <typename T>
void
out(std::ostream& os, const T& arg, const tag<out_methods::member_str>)
{
os << arg.str();
}
template <typename T>
void
out(std::ostream&, const T&, const tag<out_methods::not_at_all>)
{
// This function will never be called but we provide it anyway such that
// we get better error messages.
throw std::logic_error {};
}
template <typename T, typename = void>
struct can_directly : std::false_type {};
template <typename T>
struct can_directly
<
T,
decltype((void) (std::declval<std::ostream&>() << std::declval<const T&>()))
> : std::true_type {};
template <typename T, typename = void>
struct can_to_string : std::false_type {};
template <typename T>
struct can_to_string
<
T,
decltype((void) (std::declval<std::ostream&>() << to_string(std::declval<const T&>())))
> : std::true_type {};
template <typename T, typename = void>
struct can_member_str : std::false_type {};
template <typename T>
struct can_member_str
<
T,
decltype((void) (std::declval<std::ostream&>() << std::declval<const T&>().str()))
> : std::true_type {};
template <typename T>
constexpr out_methods
decide_how() noexcept
{
if (can_directly<T>::value)
return out_methods::directly;
else if (can_to_string<T>::value)
return out_methods::to_string;
else if (can_member_str<T>::value)
return out_methods::member_str;
else
return out_methods::not_at_all;
}
template <typename T>
void
out(std::ostream& os, const T& arg)
{
constexpr auto how = decide_how<T>();
static_assert(how != out_methods::not_at_all, "cannot format type");
out(os, arg, tag<how> {});
}
}
template <typename... Ts>
void
out(std::ostream& os, const Ts&... args)
{
const int dummy[] = {0, ((void) detail::out(os, args), 0)...};
(void) dummy;
}
Then use it like so.
int
main()
{
std::ostringstream nl {"\n"}; // has `str` member
out(std::cout, streamy {}, nl, stringy {}, '\n');
}
The function decide_how gives you full flexibility in deciding how to output a given type, even if there are multiple options available. It is also easy to extend. For example, some types have a str member function instead of an ADL find-able to_string free function. (Actually, I already did that.)
The function detail::out uses tag dispatching to select the appropriate output method.
The can_HOW predicates are implemented using the void_t trick which I find very elegant.
The variadic out function uses the “for each argument” trick, which I find even more elegant.
Note that the code is C++14 and will require an up-to-date compiler.
Based on the answer of #MSalters (credits goes to him), this one solves my problem and should make a complete answer.
#include <iostream>
#include <string>
#include <type_traits>
struct foo_t {};
std::string to_string(foo_t) {
return "foo_t";
}
template <class CharT, class Traits, class T>
typename std::enable_if<std::is_same<CharT, char>::value,
std::basic_ostream<CharT, Traits>&>::type
operator<<(std::basic_ostream<CharT, Traits>& os, const T& x) {
return os << to_string(x);
}
int main() {
std::cout << std::string{"123"} << std::endl;
std::cout << foo_t{} << std::endl;
}

Detect operator at compile time without implicit conversions

I am using the C++03 method to detect the presence of a function at compile time. I have to use this method rather than the void_t method even though I'm using C++14 because I have to support GCC 4.9, and it errors when using the void_t method (strangely only Ubuntu 14's GCC 4.9 has this problem, not Fedora's, but it's fixed across the board in GCC5+ AFAICT).
Specifically I am checking for the presence of operator<<(std::ostream&, const T&) so that I can have a pretty print function that takes any type. When the function gets called, you get the regular ostream output if the type supports it, and you get a fallback message about there being no implementation when the operator is not defined. Code at the bottom.
This has worked pretty well for me so far, until I ran into a type defined by a 3rd party library that I can't change. The type has implicit conversion operators to both bool and float. This means when the SFINAE check is done to see if s << t is valid I get a compiler error because s << t is ambiguous. In this case I'd prefer for it to just report there is no implementation like normal, rather than try to pick an implicit conversion. Is there a way to change the SFINAE check to make this possible? I have checked and the void_t method with GCC5 appears to do what I want (commented out in the code below), but I can't use it yet for the aforementioned reasons.
Test case:
#include <iostream>
#include <typeinfo>
#include <type_traits>
namespace detail {
namespace has_ostream_operator_impl {
typedef char no;
typedef char yes[2];
struct any_t {
template<typename T> any_t( T const& );
};
no operator<<( std::ostream const&, any_t const& );
yes& test( std::ostream& );
no test( no );
template<typename T>
struct has_ostream_operator {
static std::ostream &s;
static T const &t;
// compiler complains that test(s << t) is ambiguous
// for Foo
static bool const value = sizeof( test(s << T(t)) ) == sizeof( yes );
};
}
template<typename T>
struct has_ostream_operator :
has_ostream_operator_impl::has_ostream_operator<T> {
};
// template<class, class = std::void_t<>>
// struct has_ostream_operator : std::false_type {};
// template<class T>
// struct has_ostream_operator<
// T,
// std::void_t<
// decltype(std::declval<std::ostream&>() << std::declval<const T&>())>>
// : std::true_type {};
}
template<class X>
std::enable_if_t<
detail::has_ostream_operator<X>::value
&& !std::is_pointer<X>::value>
prettyPrint(std::ostream& o, const X& x)
{
o << x;
}
template<class X>
std::enable_if_t<
!detail::has_ostream_operator<X>::value
&& !std::is_pointer<X>::value>
prettyPrint(std::ostream& o, const X& x)
{
o << typeid(x).name()
<< " (no ostream operator<< implementation)";
}
template<class X>
void prettyPrint(std::ostream& o, const X* x)
{
o << "*{";
if(x) {
prettyPrint(o, *x);
} else {
o << "NULL";
}
o << "}";
}
struct Foo {
operator float() const {
return 0;
}
operator bool() const {
return false;
}
};
struct Bar {};
int main()
{
Bar x;
Foo y;
prettyPrint(std::cout, 6); // works fine
std::cout << std::endl;
prettyPrint(std::cout, Bar()); // works fine
std::cout << std::endl;
prettyPrint(std::cout, x); // works fine
std::cout << std::endl;
prettyPrint(std::cout, &x); // works fine
std::cout << std::endl;
// prettyPrint(std::cout, y); // compiler error
std::cout << std::endl;
return 0;
}
Well, you don't have to use void_t (which is syntax sugar, anyway). Bog-standard expression SFINAE is supported by GCC 4.9:
template <typename, typename = void>
struct has_ostream_operator : std::false_type {};
template <typename T>
struct has_ostream_operator<T, decltype(void(std::declval<std::ostream&>() << std::declval<const T&>()))>
: std::true_type {};
works fine on Wandbox's GCC 4.9.

Is there a way to find out if a class has an overloaded operator?

I am writing a template class where I need a method to print out element class into stdout. But I am having a problem writing it - what if cout << or operator const char*() is not defined or overloaded in my element class?
Is there a way to find it out to maybe throw an exception and not get compilation error?
If the operator is not overloaded, your program can not compile. This is a compile time error and there is no way to delay that until runtime.
A way around would be to not use an operator, but a function pointer. If the operation is not supported, than the function pointer could be set to 0 which you can detect at runtime.
class A {
public:
int q; // some data
typedef std::function<void(std::ostream& os, const A&)> PrinterFunc;
PrinterFunc func;
friend std::ostream& operator<<(std::ostream& os, const A& a) {
if(!a.func) {
throw "Not supported";
}
func(os,a);
return os;
}
};
A a;
a.func = [](std::ostream& os, const A& a) { os << "hello " << a.q; }
std::cout << a << std::endl; // will print
A b;
std::cout << b << std::endl; // will throw
This example uses C++11 and <functional>. For C++03 you would have to use a "normal" function pointer.
You might use some SFINAE to test if an (formatted) output operator exists:
#include <iostream>
// HasFormattedOutput
// ============================================================================
namespace HasFormattedOutput {
namespace Detail
{
struct Failure{};
}
template<typename OutputStream, typename T>
Detail::Failure operator << (OutputStream&, const T&);
template<typename OutputStream, typename T>
struct Result : std::integral_constant<
bool,
! std::is_same<
decltype(std::declval<OutputStream&>() << std::declval<T>()),
Detail::Failure
>::value
> {};
} // namespace HasFormattedOutput
template <typename T, typename OutputStream = std::ostream>
struct has_formatted_output : std::conditional<
HasFormattedOutput::Result<OutputStream, T>::value,
std::true_type,
std::false_type>::type
{};
// Test
// ============================================================================
struct X {};
int main() {
std::cout.setf(std::ios_base::boolalpha);
std::cout << has_formatted_output<const char*>() << '\n';
std::cout << has_formatted_output<X>() << '\n';
}
(C++11)