Compile time deduction of template member function - templates

Is it possible to get the return type of a template member function at compile time?
I guess I need something along the lines of:
template<class T>
struct SomeClass
{
// T must have a function foo(int), but do not know the
// return type, it could be anything
using RType = ??? T::foo(int) ???; // Is it possible to deduce it here?
}

What you want to do can be achieved by using the decltype operator together with the std::declval template.
decltype(EXPRESSION) yields – at compile time – the type that EXPRESSION would have. The EXPRESSION itself is never evaluated. This is much like sizeof(EXPRESSION) returns the size of whatever EXPRESSION evaluates to without ever actually evaluating it.
There is only one problem: Your foo is a non-static member function so writing decltype(T::foo(1)) is an error. We somehow need to obtain an instance of T. Even if we know nothing about its constructor, we can use std::declval to obtain a reference to an instance of it. This is a purely compile-time thing. std::declval is actually never defined (only declared) so don't attempt to evaluate it at run-time.
Here is how it would look together.
#include <type_traits>
template <typename SomeT>
struct Something
{
using RetT = decltype(std::declval<SomeT>().foo(1));
};
To see that it actually works, consider this example.
struct Bar
{
float
foo(int);
};
struct Baz
{
void
foo(int);
};
int
main()
{
static_assert(std::is_same<float, Something<Bar>::RetT>::value, "");
static_assert(std::is_same<void, Something<Baz>::RetT>::value, "");
}
While this does what I think you have asked for, it is not ideal in the sense that if you attempt to instantiate Something<T> with a T that doesn't have an appropriate foo member, you'll get a hard compiler error. It would be better to move the type computation into the template arguments such that you can benefit from the SFINAE rule.
template <typename SomeT,
typename RetT = decltype(std::declval<SomeT>().foo(1))>
struct Something
{
// Can use RetT here ...
};

If you know the argument types to your function call the following should work:
template<typename T>
struct X
{
typedef typename decltype(std::declval<T>.foo(std::declval<int>())) type;
};
If you don't you can still deduce the type of the function pointer and extract the return type:
template<class F>
struct return_type;
template<class C, class R, class... Args>
struct return_type<R(C::*)(Args...)>
{ using type = R; };
template<typename T>
struct X
{
typedef typename return_type<decltype(&T::foo)>::type type;
};
This will fail if T::foo is an overloaded function or member of T.
Unfortunately it is only possible to know the return type of some expression if you know with what arguments you are going to call it (which, unfortunately, often is a different place from where you need to know the return type)...

Related

How to get the type of function pointer of templated function from invocation

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>);

Deduce template argument of outer type [duplicate]

I have a problem with inner classes in class templates. I have a template class (say: Matrix<T>), and a subclass (say: Matrix<T>::Row). Now I want to to write a function which operates on instances of the subclass (say: negate(Matrix<T>::Row &)). I tried to declare the function with template<class T> negate(typename Matrix<T>::Row &), but when I try to use it, the compiler tells me that it cannot find a match.
Here's an abstract example:
template<class T>
class A
{
public:
class B
{
};
};
template<class T>
void x(typename A<T>::B &)
{
}
int main()
{
A<int>::B b;
x(b); // doesn't work: Error: Could not find a match
// for x<T>(A<int>::B) needed in main().
x<int>(b); // works fine
}
Why does the compiler does not manage to find x in the first case? Is there a way to modify this that it works (without explicitly specifying the type int)?
(I also have similar problems where x is of the form template<class T, class S> void x(typename A<T>::B &, const S &);, whence I would really like not to be forced to explicitly name all types while doing the call.)
I have tried this with g++ 4.4.3, g++ 4.5.2, and Sun Studio 5.9, all give the same result. Thanks a lot in advance for anything helpful!
How should the compiler be able to deduce this? Imagine the following setup:
struct A { typedef int T; };
struct B { typedef int T; };
template <typename S> void foo(typename S::T);
Now when you say int x; foo(x);, there's no way to match this unambiguously.
The point is that you are not deducing a template parameter from a given class template, but rather just an arbitrary, free-standing type. The fact that that type was defined inside another class is not relevant for that.
That is non-deducible context. That is why the template argument cannot be deduced by the compiler.
Just imagine, you might have specialized A as follows:
template <>
struct A<SomeType>
{
typedef std::map <double, double> B;
};
Now this specialization has a nested type called B which is a typedef of std::map<double,double>.
So how would the compiler deduce the type SomeType, given that A<SomeType>::B is std::map<double, double>?
And in fact, there can be many such specializations, as such:
template <>
struct A<SomeOtherType>
{
typedef std::map <double, double> B;
};
Even this specialization has B as nested type.
Now if I say A<T>::B is std::map<double,double>, then can you say what T is? Is it SomeType? or SomeOtherType?
It would need to deduce the type T for the call to template function x, and template argument deduction is only allowed in a specific set of circumstances:
http://publib.boulder.ibm.com/infocenter/compbgpl/v9v111/index.jsp?topic=/com.ibm.xlcpp9.bg.doc/language_ref/template_argument_deduction.htm
A<T>::B
does not seem to be one of them :/

avoid specifying redundant template parameters which contain templated function pointer

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.

Prevent templated member function from being instantiated for a given type

I have a templated matrix class that I explicitly instantiate for various POD types and custom class types. Some of the member functions however don't make sense for a few of such custom types. For example:
Matrix<int> LoadFile(....); // This makes sense
Matrix<My_custom_class> LoadFile(...); //This doesn't make sense in the context of the custom class
Can I prevent the instantiation of the LoadFile function (which is a member function) for Matrix objects of select types? So far I have avoided the issue by making LoadFile a friend function and then explicitly controlling its instantiation. But I want to know if I can do this when LoadFile is a member function of Matrix.
The first question is whether you really need to control this. What happens if they call that member function on a matrix that stores My_custom_class? Can you provide support in your class (or the template) so that the member function will work?
If you really want to inhibit the use of those member functions for some particular type, then you can use specialization to block the particular instantiation:
template <typename T>
struct test {
void foo() {}
};
template <>
inline void test<int>::foo() = delete;
Or even just add static_asserts to the common implementation verifying the preconditions for what types is it allowed or disallowed?
template <typename T>
struct test {
void foo() {
static_assert(std::is_same<T,int>::value || std::is_same<T,double>::value,
"Only allowed for int and double");
// regular code
}
};
with std::enable_if, this is the best I can come up with
template< typename T >
struct Matrix {
template< typename T >
Matrix< typename std::enable_if<std::is_integral<T>::value, T>::type >
LoadFile()
{
return Matrix<T>();
}
};
Matrix<int> a;
Matrix<int> b = a.LoadFile<int>()
only type int compile while other don't.
Can I prevent the instantiation of the LoadFile function (which is a member function) for Matrix objects of select types?
Your best bet here would be to use a static_assert that would create a compiler error when you attempt to call the method in a version of the class instantiated with a blocked type. Using std::enable_if, and other methods that would selectively "disable" a method itself would require you to create partial or full specializations of the class with and without the methods in question in order to prevent compiler errors. For instance, AFAIK, you cannot do the following:
template <typename T>
struct test
{
static const bool value = false;
};
template<>
struct test<double>
{
static const bool value = true;
};
template<typename T>
struct example
{
void print() { cout << "Printing value from print()" << endl; }
typename enable_if<test<T>::value, T>::type another_print()
{
cout << "Printing value from another_print()" << endl;
return T();
}
};
If you attempted to instantiate an example<int>, etc., you would end up with a compiler error at the point of instantiation of the object type. You couldn't simply call example<int>::print() and be okay, and only run into a problem if you chose to call example<int>::another_print(). Specializations of example<T> could get you around the issue, but that can be a bit of a mess. As originally surmised, a static_assert would probably be the easiest case to handle, along with a nice message to the end-user explaining what went wrong.
Keep in mind that creating compiler errors is the goal, and it's a good one to have. If you blocked a method from being instantiated, and the end-user decided to invoke it, you'd end up with a compiler error either way. The version without the static_assert will leave a lot of head-scratching as the user of your class attempts to parse a probably very verbose compiler error message, where-as the static_assert method is direct and to the point.
If the selected set of types is known at compile time, and you are using c++11 with a compiler that supports type aliases, uniform initialization and constexpr (for example gcc 4.7) you can make your code a bit cleaner like this (from previous example above by yngum):
template <bool Cond, class T = void>
using enable_if_t = typename std::enable_if<Cond, T>::type;
template< typename T >
struct Matrix {
template< typename T >
//std::is_integral has constexpr operator value_type() in c++11. This will work thanks to uniform init + constexpr. With the alias, no more need for typename + ::type
Matrix<enable_if_t<std::is_integral<T>{}>>
LoadFile()
{
return Matrix<T>();
}
};
Matrix<int> a;
Matrix<int> b = a.LoadFile<int>();
Beware of compatibility of this code, though, because these features have been only recently supported and some compilers don't do yet. You can see more about c++11 compiler support here.
If you could use the TypeLists from the ( http://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315 ) - Loki you could implement something like:
template<bool>
struct Static_Assert;
template<>
struct Static_Assert<true>{};
class B{};
template<typename T>
class A{
public:
A(){
Static_Assert< 0 == utils::HasType<T, TYPELIST_2(B,int) >::value >();
}
};
Then your HasType would be something like:
template<typename T, typename TList>
struct HasType{
enum { value = 0+HasType< T, typename TList::Tail >::value };
};
template<typename T>
struct HasType< T, NullType >{
enum { value = 0 };
};
template<typename T, typename U>
struct HasType< T, TypeList<T, U> >{
enum { value = 1 };
};
In the list you can add the classes which you would like prevent to be passed as the template parameters.

How to deduce class type from method type in C++ templates?

In templates as shown below, I would like the call Run(&Base::foo) succeed without the need to name the Base type twice (as is done in the compiling Run<Base>(&Base::foo) call). Can I have that? Possibly without adding a ton of Boost headers?
With the provided code, I get an error of:
prog.cpp:26: error: no matching function for call to ‘Run(bool (Base::*)())’
(you can fiddle with the snippet at http://ideone.com/8NZkq):
#include <iostream>
class Base {
public:
bool foo() { return true; }
};
Base* x;
template<typename T>
struct Traits {
typedef bool (T::*BoolMethodPtr)();
};
template<typename T>
void Run(typename Traits<T>::BoolMethodPtr check) {
T* y = dynamic_cast<T*>(x);
std::cout << (y->*check)();
}
int main() {
Base y;
x = &y;
Run<Base>(&Base::foo);
Run(&Base::foo); // why error?
}
The T in Traits<T>::BoolMethodPtr is in a non-deduced context, so the compiler will not deduce automatically from the call what type T should be.
This is because there could be code like this:
template<typename T>
struct Traits {
typedef bool (T::*BoolMethodPtr)();
};
template<>
struct Traits<int> {
typedef bool (Base::*BoolMethodPtr)();
};
Run(&Base::foo); /* What should T be deduced to? Base and int are both equally possible */
If you can do without the Traits<T> class, you can write Run as:
template<class Class>
void Run(bool (Class::*check)()) {
Class* y = dynamic_cast<Class*>(x);
std::cout << (y->*check)();
}
In this context, Class can be deduced to mean Base
To pick apart a type, any type, use partial specialization. There is no function template partial specialization, so you'll need to directly parameterize the function on its argument type and retrieve the class type inside.
template< typename T >
struct get_host_class; // most types are not ptmfs: don't implement this
template< typename C >
struct get_host_class< bool (C::*)() > { // implement partial specialization
typedef C host;
typedef void sfinae; // disallow function for non ptmf arguments
};
template< typename T >
typename get_host_class<T>::sfinae Run( T check) {
typedef T BoolMethodPtr; // or something
typedef typename get_host_class< T >::host host;
}
I think this is a non deduced context.
$14.8.2.5/5- "The non-deduced contexts
are: — The nested-name-specifier of a
type that was specified using a
qualified-id."
I think this is the quote that applies in this case. But some template gods need to ratify my understanding.
When the compiler tries to match a template argument, it only considers the primary class type. In other words, when it encounters the expression:
Run(&Base::foo);
...and it's trying to figure out the template parameter for Run, it only considers the type of foo itself, and doesn't consider whatever class foo is a part of.
EDIT:
And the type of foo is bool(Base::*)(void), but what you want the compiler to find is just Base