I have a function template which takes a templated parameter:
template <class R>
RefT<R> make_ref(R& res) {
return RefT<R>(&res);
}
I either want to prevent R from being any kind of iterator, or, if this is easier, I want to have a overload that the compiler will prefer to use for iterators which calls make_ref again with the iterator dereferenced.
Best approach would be combining the two, so the compiler prefers using iterator specific overload, and refuses to use the non-specific version.
I would like consumers of the code to be able to call make_ref(something) without having to think about whether the something is an iterator or not - I just need to do something different if it is, and if that's not possible, give a useful error message to the consumer.
First the traits (you may have to tweak it with your requirements):
template <typename T>
auto is_iterator_impl(T* it)
-> decltype(**it, ++(*it), (*it) == (*it), std::true_type());
template <typename T>
auto is_iterator_impl(...) -> std::false_type;
template <typename T>
using is_an_iterator = decltype(is_iterator_impl<T>(0));
Note: using std::iterator_traits<IT> may be a good alternative.
With SFINAE, you may do
template <class R>
std::enable_if_t<!is_an_iterator<R>::value, RefT<R>>
make_ref(R& res) {
return RefT<R>(&res);
}
template <class R>
std::enable_if_t<is_an_iterator<R>::value && !std::is_pointer<R>::value, RefT<R>> // you may want to change return type
make_ref(R& res) {
// Implementation for iterator
}
template <class R>
std::enable_if_t<std::is_pointer<R>::value, RefT<R>> // you may want to change return type
make_ref(R& res) {
// Implementation for iterator
}
Note: as you want to manage pointer differently, I also use std::is_pointer in addition to the custom is_an_iterator.
Note: The conditions should not have overlap, else you have conflict.
Live Demo
I used is_iterator from here: https://stackoverflow.com/a/4336298/678093
This traits struct is used with SFINAE to only enable make_ref for non-iterator types:
#include <type_traits>
template<class T>
struct is_iterator
{
static T makeT();
typedef void * twoptrs[2]; // sizeof(twoptrs) > sizeof(void *)
static twoptrs & test(...); // Common case
template<class R> static typename R::iterator_category * test(R); // Iterator
template<class R> static void * test(R *); // Pointer
static const bool value = sizeof(test(makeT())) == sizeof(void *);
};
// just to make it compile
template <typename R>
struct RefT{};
template <class R, typename std::enable_if<!is_iterator<R>::value>::type* = nullptr>
RefT<R> make_ref(R& res)
{
return RefT<R>(&res);
}
int main()
{
int* a;
make_ref(a); // fails to compile
int b;
make_ref(b); // compiles once RefT is correct
return 0;
}
An alernative solution is to use std::iterator_traits:
template <class R, typename std::enable_if<std::is_same<typename std::iterator_traits<R>::value_type, void>::value>::type* = nullptr>
RefT<R> make_ref(R& res)
{
return RefT<R>(&res);
}
This could also be done by using SFINAE with std::iterator_traits, would handle all cases that previous answers handle (pointers and types having internal iterator_category typedef) but:
no need to write your own traits (like is_iterator) to do this, or at least most of the template machinery is encapsulated in iterator_traits
could also handle potential user defined iterators that were having their own iterator_traits specialization without using the generic iterator_category typedef, not sure if this relevant/legal technique but definitely possible
Related
I write interfaces through concepts for implementation validation.
There are no problems with conventional methods:
// Interface realization
struct Realization
{
int* TestMethod(const std::string& aStr)
{
return (int *) aStr.c_str();
}
};
// Concept
template <typename T>
concept IRealization = std::is_same_v<decltype(&T::TestMethod), int* (T::*)(const std::string&)>;
// and then, for example
void Check()
{
static_assert(IRealization<Realization>)
}
but when I try to write a similar check for a template method:
// Interface realization
struct Realization
{
template <typename T>
int* TemplateMethod(const T& aStr)
{
return (int *) aStr.c_str();
}
};
, I run into a problem of dectype a template method, because I cant write
decltype(&RealizationImpl::TemplateMethod)
(at the time of checking the interface, I do not know the type that will be substituted)
Please tell me, can I somehow get the signature of the template function without type, or otherwise solve my problem? Thanks!
You should not write concepts like this. A concept should never check for something as specific as a member function with an exact signature. A concept should instead say that, given an instance of the type in question, I should be able to do i.memberFunc(...), where ... is the list of parameters.
For example, your "IRealization" concept (please don't prefix concepts with I. Concepts are not interfaces) ought to say "T must have a member function which can be called given a std::string argument and results in something which is convertible to an int." That would look like:
template <typename T>
concept IRealization = requires(T t, std::string str)
{
{ t.TestMethod(str) } -> convertible_to<int>;
};
This allows the user to provide a TestMethod that takes, for example, std::string_view instead of std::string. There's no point in being so incredibly restrictive on the type.
A concept that checks for T having a member function which is callable with some type U would have to be templated on both T and U:
template <typename T, typename U>
concept IRealization = requires(T t, U u)
{
{ t.TestMethod(u) } -> convertible_to<int>;
};
What is the problem with adding another type to the concept?
// Concept
template <typename T, typename U>
concept IRealization = std::is_same_v<decltype(&T::template TestMethod<U>), int* (T::*)(const U&)>;
For instance.
You could even make it prettier by creating a typedef -
template<typename T, typename U>
using FuncT = decltype(&T::template TestMethod<U>);
Can I write a template function taking an argument T that calls a member function foo if it exists on T, and if it doesn't calls a free function foo(T) instead (and fails to compile if neither exists)?
Something like:
template<typename T>
int call_foo(T t) {
// if T::foo() exists
return t.foo();
// else return foo(t);
}
How about the reverse case: preferring a free function foo before the member function? I cannot use any features introduced after C++11.
This isn't too hard. There are many methods of checking whether an arbitrary expression is valid. You can combine this with if constexpr in C++17 or tag dispatch earlier to get the behaviour you desire.
This uses C++17, but everything can be done in prior versions:
#include <type_traits>
#include <utility>
// This is just one way to write a type trait, it's not necessarily
// the best way. You could use the Detection Idiom, for example
// (http://en.cppreference.com/w/cpp/experimental/is_detected).
template <typename T, typename = void>
struct has_member_fn
: std::false_type
{};
// std::void_t is a C++17 library feature. It can be replaced
// with your own implementation of void_t, or often by making the
// decltype expression void, whether by casting or by comma operator
// (`decltype(expr, void())`)
template <typename T>
struct has_member_fn<T,
std::void_t<decltype(std::declval<T>().foo())>>
: std::true_type
{};
template <typename T, typename = void>
struct has_free_fn
: std::false_type
{};
template <typename T>
struct has_free_fn<T,
// Be wary of ADL. You're basically asking the compiler,
// "What's the result of foo(T{}) if I were to call that
// here?" That syntax can call functions via ADL
std::void_t<decltype(foo(std::declval<T>()))>>
: std::true_type
{};
template <typename T>
int call_foo(T t) {
// if constexpr is C++17, but you can use tag dispatch to
// do the same in prior versions
if constexpr (has_member_fn<T>::value) {
return t.foo();
} else {
// you could make this an `else if constexpr (has_free_fn<T>::value)`
// and provide a better case for if neither exists
return foo(t);
}
}
Live on Godbolt
Pre C++17 you can's compile/not compile different parts of the same function with if constexpr.
So, pre C++17, you have to do, somewhere, two different functions.
An example: if you prepare a couple of helper functions
template <typename T>
auto call_foo_h (T t, int) -> decltype( t.foo() )
{ return t.foo(); }
template <typename T>
auto call_foo_h (T t, long) -> decltype( foo(t) )
{ return foo(t); }
that are SFINAE enabled only if T::foo() exist (the first one) or if a free foo() exist (the second one), you can write call_foo() as follows
template <typename T>
int call_foo (T const & t)
{ return call_foo_h(t, 0); }
//......................^ a int value
Observe the second (unused) parameter in call_foo_h(); an int in the T::foo() version, a long in the free version.
Here is the trick: calling call_foo_h with an int (0) you call preferably the int version (the T::foo()), when available, and the long version otherwise.
How about the reverse case: preferring a free function foo before the member function?
In this case write call_foo() as follows
template <typename T>
int call_foo (T const & t)
{ return call_foo_h(t, 0L); }
//......................^^ a long value
That is: call call_foo_h with a long value, giving the precedence to the free foo() version.
I have problem similar to Passing different lambdas to function template in c++ but now with wrappers created by std::bind instead of lambdas.
I have two overloads of method Add that take different forms of std::function:
template<typename T>
struct Value
{
T value;
};
template <typename T>
void Add(Value<T> &value, function<bool()> predicate)
{
}
template <typename T>
void Add(Value<T> &value, block_deduction<function<bool(const Value<T> &)>> predicate)
{
}
This now works fine with lambdas but fails with functors bound with std::bind:
struct Predicates
{
bool Predicate0() { return true; }
bool Predicate1(const Value<int> &) { return true; }
};
Predicates p;
Add(i, std::bind(&Predicates::Predicate0, &p));
fails with
error C2668: 'Add': ambiguous call to overloaded function
and
Add(i, std::bind(&Predicates::Predicate1, &p, _1));
fails with static assert (Visual C++ 2015, Update 3):
tuple index out of bounds
Is there a way to make it work both with lambdas and bound functors? I would think of using SFINAE to enable the individual overload based on is_bindable_expression and checking the argument type but I'm failing to put it together.
Stop using std::bind. It is a mess of random features and quirks.
Todays quirk is that std::bind will accept an unlimited number of arguments and discard any extra ones. Tomorrow you might run into the fact that passing std::bind result to std::bind does strange magic.
std::bind was ported over to boost at the same time lambdas where added to the language. Lambdas solve almost every problem bind does in just as clear syntax and fails to have the myraid of quirks bind does, especially post C++14 when auto lambdas are available. (Most C++11 compilers also supported auto lambda).
You can write functions so that one or the other is the preferred overload when they both apply. But doing so adds a pile of noise to your interface, and in this case about the only reason why you'd want that preference is because std::bind is doing something stupid.
Engineering around a poorly designed bit of std library is not worth it. Simply stop using that poorly designed bit of std library, or at point of use cast explicitly.
Failing that, do this:
template <class T, class F,
std::enable_if_t<
std::is_convertible<
std::result_of_t<std::decay_t<F> const&(Value<T> const&)>,
bool
>{}, int
> = 0
>
void Add(Value<T> &value, F&& f)
{
// do pass f Value<T>
}
template <class T, class F,
std::enable_if_t<
!std::is_convertible<
std::result_of_t<std::decay_t<F> const&(Value<T> const&)>,
bool
>{}
&& std::is_convertible<
std::result_of_t<std::decay_t<F> const&()>,
bool
>{}, int
> = 0
>
void Add(Value<T> &value, F&& f)
{
// do not pass f Value<T>
}
where we throw some nasty SFINAE detection on which of the two overloads you want to use, and explicitly prefer one.
This is not worth it.
I don't think you can do what you want.
You can use is_bind_expression to check if your argument is a type produced by a call to std::bind, but there is no way to tell how many arguments the callable expects. As cpplearned mentioned in the comments, this is a feature of std::bind:
If some of the arguments that are supplied in the call to g() are not
matched by any placeholders stored in g, the unused arguments are
evaluated and discarded.
That means that both overloads are equally valid.
If you don't mind sharing the same overload for all bind results, you can pass all the parameters and let them be discarded at will:
template <typename T>
void AddImpl(Value<T> &value, function<bool()> predicate, std::false_type)
{
predicate();
}
template <typename T>
void AddImpl(Value<T> &value, block_deduction<function<bool(const Value<T> &)>> predicate, std::false_type)
{
predicate(value);
}
template <typename T, typename U>
void AddImpl(Value<T>& value, U&& bind_expression, std::true_type)
{
bind_expression(value);
}
template<typename T, typename U>
void Add(T&& t, U&& u)
{
AddImpl(std::forward<T>(t), std::forward<U>(u), std::is_bind_expression<std::decay_t<U>>{});
}
demo
But this is similar to using boolean parameters. In my opinion it'd be better for readability to dispatch on properly named tags:
template <typename T>
void AddImpl(Value<T> &value, function<bool()> predicate, tag::default_)
{
predicate();
}
template <typename T>
void AddImpl(Value<T> &value, block_deduction<function<bool(const Value<T> &)>> predicate, tag::default_)
{
predicate(value);
}
template <typename T, typename U>
void AddImpl(Value<T>& value, U&& bind_expression, tag::bind)
{
bind_expression(value);
}
template<typename T, typename U>
void Add(T&& t, U&& u)
{
AddImpl(std::forward<T>(t), std::forward<U>(u), tag::get_tag<std::decay_t<U>>{});
}
with tags defined as
namespace tag
{
struct default_{};
struct bind{};
template<typename T, typename = void>
struct get_tag : default_ {};
template<typename T>
struct get_tag<T, std::enable_if_t<std::is_bind_expression<T>::value>> : bind {};
}
demo
I am trying to make some file streamer that can read or write different types. Everything works except for the reading part with specific method. That method returns std::unique_ptr<T> when called and is a "wrapper" for another method that returns T. For some reason compiler does not use this method instead it tries to compile it with the other method (the one that returns T). The compilation fails because of this. I've already tried to search around internet but I can not find any accurate answer. Could you please help me with this.
The two methods I have defined:
template <typename T>
T read()
{
T obj;
obj.readFromFile<T>();
return std::move(obj);
}
and
template <
typename T,
template<typename> class D,
template<typename, typename> class Container
>
typename std::enable_if_t<
std::is_same<Container<T, D<T>>, std::unique_ptr<T, D<T>>>::value,
Container<T, D<T>>
>
read()
{
return std::move(std::make_unique<T, D<T>>(readFromFile<T>()));
}
The latter method is the one that I am trying to call.
When I write something like this:
std::unique_ptr<A> AfromFile = fileStreamer.read<std::unique_ptr<A>>()
compiler tries to compile it with the first method (template <typename T> T read() {...}) and the compilation fails. I could make this work if I made unique_ptr object first and than do the copy assignment to *unique_ptr<A> object but this is no good for me because i use some macro over those two functions and I cannot make unique_ptr<A> object or object A it self prior to calling the macro. Just for info I am using Visual Studio 2015.
Is there any way to make this work without any significant modification? I also found one suggestion that basically says you have to add a pointer parameter to one function and then call it with static_cast<Obj>(nullptr) as an argument but this does not count in my example.
Thanks for your help.
Update:
I just want to make a remark that all solutions below did work for me however the easiest way to fix my problem was solution provided by Barry.
Thx again for helping me!
It seems you want partial specialization, and as partial specialization on function is not possible, you may forward to class:
template <typename T> struct helper
{
T operator() const
{
T obj;
obj.readFromFile<T>();
return obj;
}
};
template <typename T, typename D>
struct helper<std::unique_ptr<T, D>>
{
std::unique_ptr<T, D> operator() const
{
return std::make_unique<T, D>(readFromFile<T>());
}
};
template <typename T>
T read()
{
return helper<T>{}();
}
The problem is, while I understand your intent of:
std::unique_ptr<A> AfromFile = fileStreamer.read<std::unique_ptr<A>>();
You're not actually calling the function you think you are. You have two overloads of read:
template <class T> T read();
template <class T,
template<typename> class D,
template<typename, typename> class Container
> T read();
The first has one template parameter, the second has 3 (and some sfinae). But you're only calling read() with one template parameter, so the second overload - the one you want - isn't even an option.
For these cases, I like simply tag dispatching so that we can overload instead of having to specialize:
template <class T> struct tag{};
template <class T> T read() { return read(tag<T>{}); }
template <class T>
T read(tag<T> ) {
T obj;
obj.readFromFile<T>();
return obj; // <== NB: no move() here! That inhibits RVO
}
template <class T, class D>
std::unique_ptr<T, D> read(tag<std::unique_ptr<T, D>> ) {
/* unique_ptr case */
}
You cannot have two overloads of a function which only differ by return type. You must use SFINAE to make sure only one is enabled for any given template parameter.
The way you are trying to deduce the template parameters in the second overload is wrong. Currently, you have to specify T, D and ContainerType when you call the function. I sense you probably want to pass just one type and then deduce whether it is a std::unique_ptr.
You cannot call std::make_unique and specify a deleter type. You must call the std::unique_ptr constructor with a newly created object.
You don't need to explicitly move the returned std::unique_ptr.
This is one way to do what you want.
#include <memory>
#include <type_traits>
template<typename T>
T readFromFile() { return T(); }
template<typename T, typename D>
void helper(std::unique_ptr<T, D>);
template<typename T, typename = void>
struct is_unique_ptr : std::false_type {};
template<typename T>
struct is_unique_ptr<T, decltype(helper(std::declval<T>()))> : std::true_type {};
template<typename T, typename = std::enable_if_t<!is_unique_ptr<T>::value>>
T read()
{
return readFromFile<T>();
}
template<typename P, typename = std::enable_if_t<is_unique_ptr<P>::value>, typename = void>
P read()
{
using T = typename P::element_type;
return P(new T(readFromFile<T>()));
}
int main()
{
read<std::unique_ptr<int>>();
read<int>();
}
The C++ standard library contains the convenient template class std::move_iterator. Given the close relationship between std::move and std::forward, why is there no equivalent std::forward_iterator? Example usage:
template <typename C>
auto foo(C&& values)
{
remove_reference_t<C> result {};
result.reserve(values.size());
std::transform(std::make_forward_iterator<C>(std::begin(values)),
std::make_forward_iterator<C>(std::end(values))),
std::back_inserter(result), Bar());
return result;
}
The idea being I can now use foo like:
std::vector<ComplexType> values {/* lots of values */};
auto copied_fooed = foo(values);
// or
auto moved_fooed = foo(std::move(values));
Without having to write two foos.
I can't answer why such a thing doesn't exist. But it's certainly implementable. Basically, your C type is either an lvalue reference (in which case just pass through the argument) or it's not a reference (in which case, use std::make_move_iterator).
First, let's start with a great addition to any toolkit, almost static if (with minor changes):
namespace detail {
enum class enabler {};
}
template <bool B>
using EnableIf = std::enable_if_t<B, detail::enabler>;
And now we just use SFINAE on the two overloads:
template <typename C,
typename Iterator,
EnableIf<std::is_lvalue_reference<C>::value>...>
Iterator make_forward_iterator(Iterator i)
{
return i;
}
template <typename C,
typename Iterator,
EnableIf<!std::is_lvalue_reference<C>::value>...>
auto make_forward_iterator(Iterator i)
{
return std::make_move_iterator(i);
}
Alternatively, and this is probably simpler, could just tag-dispatch:
namespace detail {
template <typename Iterator>
Iterator make_forward_iterator(Iterator i, std::true_type )
{
return i;
}
template <typename Iterator>
auto make_forward_iterator(Iterator i, std::false_type )
{
return std::make_move_iterator(i);
}
}
template <typename C, typename Iterator>
auto make_forward_iterator(Iterator i) {
return detail::make_forward_iterator(i, std::is_lvalue_reference<C>{});
}
It is a bit more complex than that.
With an owning container, the l/r valueness of the container imply move iterators may be of use.
But for views, this does not work: moving from an rvalue view is destructive of unowned state.
Practically, this means the decision to move or not based on l/r valueness is matter for both the context and value to mutually decide, which makes it tricky.
Range-v3 and concepts may make this easier to reason about.