ADL does not work in the specific situation - c++

I've made is_iterable template as below - which checks that free functions begin/end are available (in the context of ADL) and return proper iterator object. (Which is the requirement for iterable object in ranged-for loop)
#include <utility>
#include <iterator>
#include <type_traits>
#include <vector>
template <typename T>
typename std::add_rvalue_reference<T>::type declval(); // vs2010 does not support std::declval - workaround
template <bool b>
struct error_if_false;
template <>
struct error_if_false<true>
{
};
template<typename U>
struct is_input_iterator
{
enum {
value = std::is_base_of<
std::input_iterator_tag,
typename std::iterator_traits<U>::iterator_category
>::value
};
};
template<typename T>
struct is_iterable
{
typedef char yes;
typedef char (&no)[2];
template<typename U>
static auto check(U*) -> decltype(
error_if_false<
is_input_iterator<decltype(begin(declval<U>()))>::value
>(),
error_if_false<
is_input_iterator<decltype(end(declval<U>()))>::value
>(),
error_if_false<
std::is_same<
decltype(begin(declval<U>())),
decltype(end(declval<U>()))
>::value
>(),
yes()
);
template<typename>
static no check(...);
public:
static const bool value = (sizeof(check<typename std::decay<T>::type>(nullptr)) == sizeof(yes));
};
#include <cstdio>
void write(int a)
{
printf("%d\n", a);
}
template<typename T>
typename std::enable_if<is_iterable<T>::value>::type write(const T& a)
{
for (auto i = begin(a), e = end(a); i != e; ++i) {
write(*i);
}
}
int main()
{
write(10);
std::vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(4);
write(a);
}
Above code exactly works as intended in vs2010, but not in gcc. Moreover, when I put the some random free function named 'begin', as below, it becomes broken even in vs2010.
int begin(int)
{
}
How can I make the code works? Also, any suggestion that improves the "is_iterable" concept checker would be appreciated.
added: "write" function is just a concept demonstration example - please don't invest your precious time to it. (I know it's not the best code :( ) The part needs some attention is ADL behaviour and "is_iterable" template :)

After adding std:: to begin/end - your code compiles and runs under gcc-4.6
Improvement suggestion: replace error_if_false with of enable_if

write(a); should be defined through the operator as Jerry said. Maybe make it more consise so that your code is cleaner.

Related

Compiling based on container type

In the code below, suppose that I decided to use deque instead of vector in the definition of mcc. How can I bypass cell.reserve(size) which is not defined for deque?
#include <vector>
#include <deque>
typedef std::vector<int> mcc;
//typedef std::deque<int> mcc;
void reserve(mcc& cell, int size)
{
cell.reserve(size);
}
int main()
{
mcc cell;
reserve(cell, 10);
return 0;
}
As the other answer and some comments have pointed out, in C++20, there are concepts, a feature which makes this task fairly trivial. However, as of now, C++20 support isn't complete in any compiler.
In the current C++ version, C++17, we don't have concepts. So, we need to use templates to emulate this concept behavior:
// The default case for can_reserve is false
template<typename T, typename = void>
struct can_reserve : std::false_type {};
// An overload of the struct allows us to verify we can call a value of type T
// If substitution doesn't fail, this overload is selected.
template<typename T>
struct can_reserve<T, std::void_t<decltype(std::declval<T>().reserve(1))>> : std::true_type {};
// With inline constexpr values, we can make this a type trait
template<typename T>
inline constexpr bool can_reserve_v = can_reserve<T>::value;
// We can then verify we can reserve with the types
static_assert(can_reserve_v<std::vector<int>>);
static_assert(!can_reserve_v<std::deque<int>>);
The function then becomes:
template<typename T>
void reserve(T& cell, int size)
{
if constexpr(can_reserve_v<T>)
cell.reserve(size);
}
Creating this kind of template is boilerplate-y and sometimes failure-prone. To solve that, we can use the detection idiom, which reduces the boilerplate and makes the code more readable:
// Using FluentCPP's is_detected implementation of the detection idiom
template<typename T>
using reserve_expression = decltype(std::declval<T&>().reserve(1));
template<typename T>
constexpr bool can_reserve_v = is_detected<reserve_expression, T>;
(The reserve function stays the same)
For completeness, the equivalent in C++20 would be:
template<typename T>
concept can_reserve = requires(T& t){
{ t.reserve(1) };
};
template<typename T>
void reserve(T& cell, int size)
{
if constexpr(can_reserve<T>)
cell.reserve(size);
}
There is a neat C++20 solution:
#include <vector>
#include <deque>
//typedef std::vector<int> mcc;
typedef std::deque<int> mcc;
mcc cell;
template<typename T>
void reserve(T& cell, int size)
{
if constexpr(requires{cell.reserve(size);}) {
cell.reserve(size);
}
}
int main()
{
reserve(cell, 10);
return 0;
}

Use boost::hash_value to define std::hash in C++11

Is there an easy way to do the following with C++11 & Boost:
use the standard definitions of std::hash whenever available from <functional>
use boost::hash_value to define std::hash in those cases where std::hash is missing but boost::hash_value is available in <boost/functional/hash.hpp>.
For example:
std::hash<std::vector<bool>> should come from the standard library,
std::hash<std::vector<unsigned>> should be implemented with boost::hash_value.
The first idea that comes to mind is to use SFINAE and try std::hash<> if possible and otherwise use boost::hash_value(), like this:
#include <string>
#include <functional>
#include <type_traits>
#include <boost/functional/hash.hpp>
struct my_struct_0 {
std::string s;
};
template <typename T>
struct has_std_hash_subst { typedef void type; };
template <typename T, typename C = void>
struct has_std_hash : std::false_type {};
template <typename T>
struct has_std_hash<
T,
typename has_std_hash_subst<decltype( std::hash<T>()(T()) ) >::type
> : std::true_type {};
template <typename T>
static typename std::enable_if<has_std_hash<T>::value, size_t>::type
make_hash(const T &v)
{
return std::hash<T>()(v);
}
template <typename T>
static typename std::enable_if<(!has_std_hash<T>::value), size_t>::type
make_hash(const T &v)
{
return boost::hash_value(v);
}
int main()
{
make_hash(std::string("Hello, World!"));
make_hash(my_struct_0({ "Hello, World!" }));
}
Unfortunately, there is always a default specialization of std::hash that triggers static_assert failure. This may not be the case with other libraries but it is the case with GCC 4.7.2 (see bits/functional_hash.h:60):
/// Primary class template hash.
template<typename _Tp>
struct hash : public __hash_base<size_t, _Tp>
{
static_assert(sizeof(_Tp) < 0,
"std::hash is not specialized for this type");
size_t operator()(const _Tp&) const noexcept;
};
So the above SFINAE approach doesn't work — static_assert in there is a show-stopper. Therefore, you cannot really determine when std::hash is available.
Now, this does not really answer your question but might come handy — it is possible to do this trick the other way around — check for Boost implementation first and only then fall back to std::hash<>. Consider the below example that uses boost::hash_value() if it is available (i.e. for std::string and my_struct_0) and otherwise uses std::hash<> (i.e. for my_struct_1):
#include <string>
#include <functional>
#include <type_traits>
#include <boost/functional/hash.hpp>
struct my_struct_0 {
std::string s;
};
struct my_struct_1 {
std::string s;
};
namespace boost {
size_t hash_value(const my_struct_0 &v) {
return boost::hash_value(v.s);
}
}
namespace std {
template <>
struct hash<my_struct_1> {
size_t operator()(const my_struct_1 &v) const {
return std::hash<std::string>()(v.s);
}
};
}
template <typename T>
struct has_boost_hash_subst { typedef void type; };
template <typename T, typename C = void>
struct has_boost_hash : std::false_type {};
template <typename T>
struct has_boost_hash<
T,
typename has_boost_hash_subst<decltype(boost::hash_value(T()))>::type
> : std::true_type {};
template <typename T>
static typename std::enable_if<has_boost_hash<T>::value, size_t>::type
make_hash(const T &v)
{
size_t ret = boost::hash_value(v);
std::cout << "boost::hash_value(" << typeid(T).name()
<< ") = " << ret << '\n';
return ret;
}
template <typename T>
static typename std::enable_if<(!has_boost_hash<T>::value), size_t>::type
make_hash(const T &v)
{
size_t ret = std::hash<T>()(v);
std::cout << "std::hash(" << typeid(T).name()
<< ") = " << ret << '\n';
return ret;
}
int main()
{
make_hash(std::string("Hello, World!"));
make_hash(my_struct_0({ "Hello, World!" }));
make_hash(my_struct_1({ "Hello, World!" }));
}
Hope it helps.
UPDATE: Perhaps you could use the hack described here as pointed out by #ChristianRau and make the first SFINAE approach work! Though it is very dirty :)
My answer might not be correct, but I will try to explain why I think that the answer is no.
I don't think that std::hash<T> and boost:hash<T> can be used interchangeably, so I've tried hiding object creation (even if this is not perfect solution), and return their result, which is size_t. Method should be of course chosen at compile time, so function dispatch is what comes to my mind, sample code:
template <typename T>
size_t createHash(const T& t, false_type)
{
return boost::hash<T>()(t);
}
template <typename T>
size_t createHash(const T& t, true_type)
{
return std::hash<T>()(t);
}
template<typename T>
size_t createHash(const T& t)
{
return createHash<T>(t, std::is_XXX<T>::type());
}
int main()
{
vector<unsigned> v; v.push_back(1);
auto h1 = createHash(v);
cout << " hash: " << h1;
//hash<vector<unsigned> > h2;
}
The idea of this code is simple: if you can construct type of type std::hash<T>, choose second implementation, if not - choose first one.
If the first implementation is chosen, code compiles without a problem, you can check it by using fe. std::is_array<T>::type() in a wrapper function, which is of course not true, so boost::hash implementation will be choosed. However, if you use a trait which will return true_t for a vector<unsigned>, like fe. std::is_class<T>::type() then the compiler will report "C++ Standard doesn't provide...", which is a result of a static_assert.
For this to work, we would need to force compiler to return true_t if a type is really constructible (it doesn't fail static_assert) and false_t if it doesn't. However, I don't think there is a possibility to do that.

Detecting a function in C++ at compile time

Is there a way, presumably using templates, macros or a combination of the two, that I can generically apply a function to different classes of objects but have them respond in different ways if they do not have a specific function?
I specifically want to apply a function which will output the size of the object (i.e. the number of objects in a collection) if the object has that function but will output a simple replacement (such as "N/A") if the object doesn't. I.e.
NO_OF_ELEMENTS( mySTLMap ) -----> [ calls mySTLMap.size() to give ] ------> 10
NO_OF_ELEMENTS( myNoSizeObj ) --> [ applies compile time logic to give ] -> "N/A"
I expect that this might be something similar to a static assertion although I'd clearly want to compile a different code path rather than fail at build stage.
From what I understand, you want to have a generic test to see if a class has a certain member function. This can be accomplished in C++ using SFINAE. In C++11 it's pretty simple, since you can use decltype:
template <typename T>
struct has_size {
private:
template <typename U>
static decltype(std::declval<U>().size(), void(), std::true_type()) test(int);
template <typename>
static std::false_type test(...);
public:
typedef decltype(test<T>(0)) type;
enum { value = type::value };
};
If you use C++03 it is a bit harder due to the lack of decltype, so you have to abuse sizeof instead:
template <typename T>
struct has_size {
private:
struct yes { int x; };
struct no {yes x[4]; };
template <typename U>
static typename boost::enable_if_c<sizeof(static_cast<U*>(0)->size(), void(), int()) == sizeof(int), yes>::type test(int);
template <typename>
static no test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(yes) };
};
Of course this uses Boost.Enable_If, which might be an unwanted (and unnecessary) dependency. However writing enable_if yourself is dead simple:
template<bool Cond, typename T> enable_if;
template<typename T> enable_if<true, T> { typedef T type; };
In both cases the method signature test<U>(int) is only visible, if U has a size method, since otherwise evaluating either the decltype or the sizeof (depending on which version you use) will fail, which will then remove the method from consideration (due to SFINAE. The lengthy expressions std::declval<U>().size(), void(), std::true_type() is an abuse of C++ comma operator, which will return the last expression from the comma-separated list, so this makes sure the type is known as std::true_type for the C++11 variant (and the sizeof evaluates int for the C++03 variant). The void() in the middle is only there to make sure there are no strange overloads of the comma operator interfering with the evaluation.
Of course this will return true if T has a size method which is callable without arguments, but gives no guarantees about the return value. I assume wou probably want to detect only those methods which don't return void. This can be easily accomplished with a slight modification of the test(int) method:
// C++11
template <typename U>
static typename std::enable_if<!is_void<decltype(std::declval<U>().size())>::value, std::true_type>::type test(int);
//C++03
template <typename U>
static typename std::enable_if<boost::enable_if_c<sizeof(static_cast<U*>(0)->size()) != sizeof(void()), yes>::type test(int);
There was a discussion about the abilities of constexpr some times ago. It's time to use it I think :)
It is easy to design a trait with constexpr and decltype:
template <typename T>
constexpr decltype(std::declval<T>().size(), true) has_size(int) { return true; }
template <typename T>
constexpr bool has_size(...) { return false; }
So easy in fact that the trait loses most of its value:
#include <iostream>
#include <vector>
template <typename T>
auto print_size(T const& t) -> decltype(t.size(), void()) {
std::cout << t.size() << "\n";
}
void print_size(...) { std::cout << "N/A\n"; }
int main() {
print_size(std::vector<int>{1, 2, 3});
print_size(1);
}
In action:
3
N/A
This can be done using a technique called SFINAE. In your specific case you could implement that using Boost.Concept Check. You'd have to write your own concept for checking for a size-method. Alternatively you could use an existing concept such as Container, which, among others, requires a size-method.
You can do something like
template< typename T>
int getSize(const T& t)
{
return -1;
}
template< typename T>
int getSize( const std::vector<T>& t)
{
return t.size();
}
template< typename T , typename U>
int getSize( const std::map<T,U>& t)
{
return t.size();
}
//Implement this interface for
//other objects
class ISupportsGetSize
{
public:
virtual int size() const= 0;
};
int getSize( const ISupportsGetSize & t )
{
return t.size();
}
int main()
{
int s = getSize( 4 );
std::vector<int> v;
s = getSize( v );
return 0;
}
basically the most generic implementation is always return -1 or "NA" but for vector and maps it will return the size. As the most general one always matches there is never a build time failure
Here you go. Replace std::cout with the output of your liking.
template <typename T>
class has_size
{
template <typename C> static char test( typeof(&C::size) ) ;
template <typename C> static long test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
template<bool T>
struct outputter
{
template< typename C >
static void output( const C& object )
{
std::cout << object.size();
}
};
template<>
struct outputter<false>
{
template< typename C >
static void output( const C& )
{
std::cout << "N/A";
}
};
template<typename T>
void NO_OF_ELEMENTS( const T &object )
{
outputter< has_size<T>::value >::output( object );
}
You could try something like:
#include <iostream>
#include <vector>
template<typename T>
struct has_size
{
typedef char one;
typedef struct { char a[2]; } two;
template<typename Sig>
struct select
{
};
template<typename U>
static one check (U*, select<char (&)[((&U::size)!=0)]>* const = 0);
static two check (...);
static bool const value = sizeof (one) == sizeof (check (static_cast<T*> (0)));
};
struct A{ };
int main ( )
{
std::cout << has_size<int>::value << "\n";
std::cout << has_size<A>::value << "\n";
std::cout << has_size<std::vector<int>>::value << "\n";
}
but you have to be careful, this does neither work when size is overloaded, nor when it is a template. When you can use C++11, you can replace the above sizeof trick by decltype magic

specific syntax question

Is it possible to create template to the initialization like:
template <typename C> typename C::value_type fooFunction(C& c) {...};
std::vector<string> vec_instance;
fooFunction(cont<0>(vec_instance));
fooFunction(cont<1>(vec_instance));
In general i'm interested is it possible to specify template using integer (ie. 0) instead of true type name.
And how to achieve above?
I'm not completely clear on what you're asking, but the following snippet works for me:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
template <typename C>
typename C::value_type fooFunction(const C & c) { return 0; };
/* note that fooFunction takes a ref-to-const, not a reference */
template<int N>
struct cont
{
public:
typedef int value_type;
cont(vector<string> vec) {};
};
int main()
{
std::vector<string> vec_instance;
fooFunction(cont<0>(vec_instance));
fooFunction(cont<1>(vec_instance));
}
Two changes worth noting:
An integer is not a type, so if cont is declared template <typename T>, what you have written will not work. template <int N> is the proper way to parameterize over an integral value, as templatetypedef mentioned.
I'm not sure how cont<> is defined, but from your usage it must be an object you are constructing as a temporary. You will have trouble passing this temporary as a reference into fooFunction. Note that my example above passes C as reference-to-const instead.
Yes, you can parameterize templates over non-type arguments like integers, pointers, and other templates. For example:
template <typename T, int N> struct Array {
T data[N];
/* ... other functions ... */
};
These templates work just like all the other templates you've seen, except that they're parameterized over integral values rather than types.
This link has some more info on the subject. "Modern C++ Design" and "C++ Templates: The Complete Guide" also have lots of info on how to do this.
Is this what you are after? Non-type template parameters:
template<int n> class Cont
{
public:
typedef int value_type;
};
template<>
class Cont<0>
{
public:
typedef double value_type;
value_type convert(const std::string& s) const
{
return atof(s.c_str());
}
};
template<>
class Cont<1>
{
public:
typedef long value_type;
value_type convert(const std::string& s) const
{
return atoi(s.c_str());
}
};
template <int n> typename Cont<n>::value_type fooFunction(const Cont<n>& cont, const std::string& s)
{
return cont.convert(s);
}
void test()
{
Cont<0> c0;
Cont<1> c1;
double d = fooFunction(c0,"1.0");
int i = fooFunction(c1, "-17");
}

A puzzle for template wizards

I'd like to do the following:
const int someInt;
const std::vector<int> someIntList;
const std::vector<std::vector<int>> someNestedIntList;
Marshall(someInt); // trivial case
Marshall(someIntList); // difficult case
Marshall(someNestedIntList); // difficult case
I tried the following:
template<std::vector<class Element>>
void Marshall(const std::vector<Element>& toBeMarshalled)
{
for (int i=0; i<toBeMarshalled.size(); ++i)
Marshall<Element>(toBeMarshalled[i]);
}
Regrettably, this doesn't compile, and I failed to find the right syntax for it.
Note that there has to be only a single template parameter, otherwise the marshalling of a nested list won't work.
Update: Thanks to FredOverflow's answer, I found what I was looking for. I forgot that all container classes in the standard library have a value_type typedef. This can be used as a workaround for my problem:
template <class Container>
void Marshall(const Container& toBeMarshalled)
{
for (UINT32 i=0; i<toBeMarshalled.size(); ++i)
Marshall<Container::value_type>(toBeMarshalled);
}
It is a bit of a patch, but I think it is good enough.
There are two things wrong with your template:
The template declaration is wrong. You only list the template arguments here, not the function argument types. Also, >> is parsed as shift operator.
std::vector has two template parameters. Although in your daily work you will rarely use the second, it's still there and should be listed, or your template will fail if anyone ever attempts to use it with a std::vector that doesn't use the default allocator.
This should work for all std::vector instances:
template< typename T >
void Marshall(const T& toBeMarshalled)
{
// ...
}
template< typename T, class A >
void Marshall(const std::vector<T,A>& toBeMarshalled)
{
for (typename std::vector<T,A>::size_type i=0; i<toBeMarshalled.size(); ++i)
Marshall(toBeMarshalled[i]);
}
The template declaration is wrong. Do:
template< class Element >
void marshall( std::vector< Element > const& v )
Cheers & hth.,
May I propose SFINAE and some boost metaprogramming?
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
template <class T>
struct has_begin_end
{
template <class U,
typename U::const_iterator (U::*)() const,
typename U::const_iterator (U::*)() const>
struct sfinae { };
template <class U>
static char test(sfinae<U, &U::begin, &U::end>*);
template <class>
static long test(...);
enum { value = (1 == sizeof test<T>(0)) };
typedef boost::integral_constant<bool, value> type;
};
template <class Value>
typename boost::disable_if<has_begin_end<Value>, void>::type
Marshall(const Value& value)
{
std::cout << value << ' ';
}
template <class Container>
typename boost::enable_if<has_begin_end<Container>, void>::type
Marshall(const Container& c)
{
std::for_each(c.begin(), c.end(), Marshall<typename Container::value_type>);
}
int main()
{
const int someInt = 42;
const std::vector<int> someIntList {2, 3, 5, 7};
const std::vector<std::vector<int>> someNestedIntList {{11, 13}, {17, 19}};
Marshall(someInt);
Marshall(someIntList);
Marshall(someNestedIntList);
}
The code you've pasted contains >> at the end of your template declaration. C++ compilers will interpret that not as two closing angle brackets, but as a single right-shift operator.
Try template<std::vector<class Element> >, with a space between the brackets.