template<typename T>
Ref<Iterator<T> > GetFilterIterator(Ref<Iterator<T> > i, boost::function<bool(T)> pred) {
return new FilterIterator<T>(i, pred);
}
Ref<Iterator<CWorm*> > x = GetFilterIterator(worms(), &CWorm::getLocal);
And worms() returns a Ref<Iterator<CWorm*> Ref> and there is bool CWorm::getLocal(); (which is a member function). And:
template<typename T> struct Ref {
// ...
};
template<typename T> struct Iterator {
// ...
};
This will fail to deduce the template argument:
Iter.h:272:27: note: candidate template ignored: failed template argument deduction [3]
Why?
If I call it with the specified template argument, i.e. GetFilterIterator<CWorm*>(worms(), &CWorm::getLocal), it doesn't complain. I wonder why it cannot deduce the template argument like this. And can I make it different somehow so that it would be able to automatically deduce the type?
Do you mean typname Iterator<T>::Ref for the type of the first parameter in the GetFilterIterator template declaration? If so, that is not a deducible context for template type parameters.
Consider:
template<>
struct Iterator<Foo> {
typedef int Ref;
};
template<>
struct Iterator<Bar> {
typedef int Ref;
};
GetFilterIterator(int(0),f);
Both Iterator<Foo>::Ref and Iterator<Bar>::Ref match the parameter passed to GetFilterIterator, an int. Which one should it pick? C++ disallows deducing template types from parameters like the one you've declared.
With the update to your question it looks like you do mean ::Ref<Iterator<T> >. I think that should be deducible then, and since the typedef Iterator<CWorm*>::Ref is ::Ref<Iterator<CWorm*> > it seems like it should be able to deduce T. I'm not sure why it's not working.
The compiler cannot deduce the template arguments because fitting to the parameters would mean a non-trivial conversion - first to Iterator<T> and then to Ref<Iterator<T> > which both require user-defined conversions. Also, directly converting the member function pointer to boost::function is similarly non-trivial for the compiler.
IBM has a list of supported template parameter deductions.
If you want your template arguments to be deduced automatically, you have to provide wrapper methods:
template <typename T>
Ref<Iterator<T> > makeIteratorRef(T val) {
return Ref<Iterator<T> >(Iterator<T>(val));
}
template <typename T>
boost::function<bool (T)> makeFn(bool (T::*fn) () const) {
boost::function<bool (T)> res = boost::bind(fn, _1);
return res;
}
...
Ref<Iterator<CWorm*> > x = GetFilterIterator(makeIteratorRef(worms()), makeFn(&CWorm::getLocal));
This way the compiler is capable of deducing the template parameters because no conversions are necessary.
By the way, I think you are overcomplicating simple things:
for (auto it = worms().begin(); it != worms().end(); ++it)
if (it->isLocal()) {
// Do something
}
This code is way more readable in C++ and even though it might not be as general it hardly makes the code worse.
Thanks to the hint from Xeo to here about that implicit type conversions are not allowed when deducing template arguments, I wondered wether the second parameter might cause problems here. I thought that it would do the type deduction from left to right and once the type is deducted, it is not a problem anymore (for the function pointer to boost::function cast).
It seems I was wrong and this was exactly the problem.
Another version of the same thing avoids the problem:
template<typename T>
struct PartialFuncWrapper {
::Ref<Iterator<T> > i;
PartialFuncWrapper(::Ref<Iterator<T> > _i) : i(_i) {}
typename Iterator<T>::Ref operator()(boost::function<bool(T)> pred) {
return new FilterIterator<T>(i, pred);
}
};
template<typename T>
PartialFuncWrapper<T> GetFilterIterator(::Ref<Iterator<T> > i) {
return PartialFuncWrapper<T>(i);
}
Then I can write:
Ref<Iterator<CWorm*> > x = GetFilterIterator(worms())(&CWorm::getLocal);
Related
Let's imagine I have some complicated templated function and I want to test that it works as expected.
In particular that when invoked with certain arguments that type of function is determined only by first argument.
For example:
template<typename T>
bool less(const T& x, const std::type_identity_t<T>& y){
return x < y;
}
Here I would like to check something (with static_assert or some test framework expect) that only first argument determines the signature of the function, something like:
std::is_same_v<decltype(less(short{1}, long{2})) , decltype(less(short{1}, double{2}))>;
But obviously this does not work since decltype will give me the result of function invocation, not the type of the function that is instantiated when I give it arguments I gave it.
Is there a way to do this(assume I can not modify the function, e.g. make it a functor with typedefed T or change it any other way)?
I tried searching for this, failed, I guess somebody asked this already but I could not find the question.
note: I know about testing behaviors, not implementation. Example is just tiny example, not something realistic.
This isn't a full answer, but something like this should_convert_to might work to test the less function:
#include <type_traits>
template <typename expected>
struct should_convert_to{
template <typename actual>
operator actual() {
static_assert(std::is_same_v<expected, actual>);
return {};
}
};
auto result = less(int{1}, should_convert_to<int>());
static_assert(std::is_same_v<decltype(result), bool>);
// error: static_assert failed due to requirement 'std::is_same_v<short, int>'
// less(int{1}, should_convert_to<short>());
You could use a wrapper class that gives you the signature:
// ...
template <typename, typename, typename = void>
struct less_fptr;
template <typename X, typename Y>
struct less_fptr<X, Y, std::enable_if_t<!std::is_convertible_v<Y, X>>> {
using type = less_fptr<X, Y>;
};
template <typename X, typename Y>
struct less_fptr<X, Y, std::enable_if_t<std::is_convertible_v<Y, X>>> {
using type = bool(*)(const X&, const std::type_identity_t<X>&);
};
// ...
static_assert(std::is_same_v<typename less_fptr<decltype(short{1}), decltype(long{2})>::type, typename less_fptr<decltype(short{1}), decltype(double{2})>::type>);
I want to have a template parameter accept a template that has a numeric template argument.
This example maybe overly simplified, but I'd like something like this:
template <int X>
struct XX
{
static const int x = X;
};
template<typename TT, TT V, template<V> TX>
void fnx(TX<V> x)
{
static_assert(V == TX::x, "IMPOSSIBLE!");
}
void fny()
{
fnx(XX<1>())
}
I must not be understanding the syntax for this, as it must be possible. How would I accomplish this?
Just fixing up your syntax a bit - since the template template parameter is improperly specified, we'd end up with something like this:
template <typename T, template <T > class Z, T Value>
// ^^^^^^^^^^^^^^^^^^^^^
void foo(Z<Value> x) { }
However, the compiler can't deduce T here - it's a non-deduced context. You'd have to explicitly provide it:
foo<int>(XX<1>{});
That's pretty annoying. I cannot even write a type trait such that non_type_t<XX<1>> is int (where that type trait does actual introspection on the type, not something that trivially returns int).
There is a proposal to improve this process (P0127) by amending the non-deduced context-ness of non-type template arguments.
Your declaration of fnx needs some work, and the type TT can't be deduced at the call site.
template<typename TT, TT V, template<TT> class TX>
void fnx(TX<V> x)
{
static_assert(V == TX<V>::x, "IMPOSSIBLE!");
}
void fny()
{
fnx<int>(XX<1>());
}
Working example: https://ideone.com/57PsCA
Compiling on C++03, I've attempted to write up a test template function that returns a pointer-to-member-function of a member function that returns int, and takes two float arguments:
template<typename TemplateClass>
int (TemplateClass::*)(float,float) Testtest(TemplateClass &A)
{
return &TemplateClass::Function;
}
But naturally, no matter what variations on the pointer-to-member-function syntax I use, the compiler complains of initialisation errors. Typedef, although it works with known classes, for obvious reasons (naming conflicts), won't accept template class arguments for classes that I can't know ahead of time which are likely to use the same function.
What non-typedef way is there to get this function to compile and return a pointer-to-member-function?
To declare it without a type alias, without type deduction, and without a trailing return type:
template<typename TemplateClass>
int (TemplateClass::* Testtest(TemplateClass &A))(float,float)
But of course this isn't what you would use in real code. Instead you would use an alias template:
template<typename T>
using return_type = int (T::*)(float,float);
template<typename TemplateClass>
return_type<TemplateClass> Testtest(TemplateClass &A)
Or return type deduction in C++14:
template<typename TemplateClass>
auto Testtest(TemplateClass &A)
Or a trailing return type (in C++11):
template<typename TemplateClass>
auto Testtest(TemplateClass &A) -> int (TemplateClass::*)(float,float)
You need this prototype:
template<typename TemplateClass>
int (TemplateClass::*Testtest(TemplateClass &A)) (float,float) { }
int (Class::*f())(float,float);
f is function taking no arguments returning pointer to member function of class Class takinf 2 floats and returning int.
And template version:
template <typename Type>
int (Type::*f())(float,float);
I reject the premise of your question. Use typedefs. Or, specifically, a type trait:
template <class T, class F>
struct make_mem_fun {
typedef F T::*type;
};
template<typename TemplateClass>
typename make_mem_fun<TemplateClass, int(float, float)>::type
Testtest(TemplateClass &A)
{
return &TemplateClass::Function;
}
That is way easier to understand than the convoluted syntax of actually returning the type. With C++11, we can turn that into an alias to drop the typename ::type stuff.
Suppose we have this code:
template <class T, void (*u)(T&)>
void Foo()
{
// store the function u internally . . .
}
There are reasons to do something like this and I won't attempt to go into them. However, is there any way to avoid having to specify type T when calling Foo()? For example, to compile, one normally needs:
Foo<int, MyIntFunction>();
But if this int can be deduced from the function pointer, is this possible:
Foo<MyIntFunction>();
EDIT I'm aware of the solution to pass the actual function pointer in as a function parameter, however this is not desired here as it has some perf drawbacks in intensive loop.
In this example u is not a function pointer, it's a type (the signature of a function pointer). If you want to store a function pointer you need to pass it.
template<class T, class F = void(*)(T&)>
void Foo(F f)
{
// store the function pointer f here
}
called like so:
struct SomeType {};
void bar(SomeType& x);
Foo(&bar);
Is this what you mean to do?
Short answer: I don't think it is possible.
Long one.. When calling a template function, you cannot omit the first parameter and specify the second: the compiler would try to match your MyIntFunction to the template parameter T. Generally, you can specify the first, but omit the second if the compiler can infer the second template parameter. In this case, this is not an option however, because you want to specify the second parameter explicitly.
The second template parameter has a dependency (T) on the first template parameter. Therefore, reversing the order of the template parameters is also not an option.
Your best bet would be to define it in a way similar to what Richard suggested:
template<class T>
void Foo(T f)
{
int a(1);
f(a); // this forces f to be a function taking an int as parameter
}
Here is a dirty implementation which basically does what the OP was asking for. It depends on too many assumptions, but could be at least something to discuss. The idea is to specify in advance all possible types which can serve as function argument, and then deduce this type.
#include<iostream>
template<typename T>
struct TD; //type display
template<typename FunctionType, typename T, typename ... Ts>
struct ArgumentDeduction
{
typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
, T
, typename ArgumentDeduction<FunctionType, Ts ...>::type
>::type type;
};
template<typename FunctionType, typename T>
struct ArgumentDeduction<FunctionType, T>
{
typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
, T
, void
>::type type;
};
template<typename FunctionType
, typename T = typename ArgumentDeduction<FunctionType, int, double>::type >
void foo()
{
TD<T>();
}
struct AvoidConversion
{
struct DummyType{};
template<typename T> DummyType operator()(T x) { return DummyType(); }
};
struct Bar : public AvoidConversion
{
using AvoidConversion::operator();
void operator()(int x);
//void operator()(double x); //try also this
};
int main()
{
foo<Bar>(); //calls the foo<Bar,int> version
}
One main assumption here is the form of the Bar functor, which in principle accepts any type, but has a relevant implementation of type void only for the single allowed type.
Again, I don't think this is rather useful, but I guess this comes closest to the OP's question up to now.
DEMO
EDIT: Otherwise, i.e. without AvoidConversion in the code above, the compiler will perform an implicit conversion and the argument deduction gives true for all types which are convertible into each other (such that, e.g., int is deduced when there is only a function taking double).
If someone sees a way to avoid this ugly AvoidConversion hack and deduce the parameter type somehow more elegant, I would be interested in seeing that.
I have some difficulties with perfect forwarding.
Here is my current level of understanding : glue Template + rvalue reference + std::forward and a special magical mode get activated where template deduction rules have not the same meaning as usual, but are crafted to allow perfect forwarding. Example :
template <typename T>
void outer(T&& t)
{
inner(std::forward<T>(t)); // perfect forwarding activated
}
But what happen if T is actually a templated class ?
For example, how can I perfect forward a std::tuple ? If use a T&& as aboce I will lost all type information of the objects contained in the tuple.
However the following code can't work :
template <typename... Args>
void outer(std::tuple<Args...>&& t)
{
inner(std::forward<std::tuple<Args...>>(t));
use_args_types_for_something_else<Args...>(); // I need to have Args available
}
int main()
{
std::tuple<int, double, float> t(4, 5.0, 4.0f);
outer(t);
}
Last gcc snapshot says :
error: cannot bind 'std::tuple<int, double, float> lvalue to
std::tuple<int, double, float>&&
So clearly, we are still in the general, non-template case where lvalue can't bind to rvalue reference. "Perfect forwading mode" is not activated
So I tried to be sneaky and pass my tuple as a template template :
template <
typename... Args
template <typename...> class T
>
void outer(T<Args...>&& t)
{
inner(std::forward<T<Args...>>(t));
use_args_type_for_something_else<Args...>();
}
But I still get the same error.
Perfect forwarding works only if the type of the parameter is a template type for the function, so the only way to achieve perfect forwarding is like in your first example:
template <typename T>
void outer(T&& t)
{
inner(std::forward<T>(t)); // perfect forwarding activated
}
The above works because it is a special case where T is deduced as SomeType& or SomeType&&.
This, however, does not mean that the type information for the tuple elements is lost for good. It is still retrievable (although I don't think you can typedef a variadic template pack). For example, you can still call use_args_types_for_something_else like this:
template <class T>
struct call_uses_args;
template <class ...Args>
struct call_uses_args<std::tuple<Args...>>
{
void call() const { use_args_types_for_something_else<Args...>(); }
};
template <typename TupleT>
void outer(TupleT&& t)
{
inner(std::forward<TupleT>(t));
call_uses_args<typename std::remove_reference<TupleT>::type>().call();
}
There might be no good general solution, though, but hopefully such situations are rare. (E.g, in this particular example, it might be simpler just to overload outer.)