Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deduction template argument C++

Tags:

c++

templates

Please, consider the code below:

template<typename T>
bool function1(T some_var) { return true; }

template <typename T>
bool (*function2())(T) {
  return function1<T>;
}

void function3( bool(*input_function)(char) ) {}

If I call

function3(function2<char>());

it is ok. But if I call

function3(function2());

compiler gives the error that it is not able to deduction the argument for template.

Could you, please, advise (give an idea) how to rewrite function1 and/or function2 (may be, fundamentally to rewrite using classes) to make it ok?

* Added *

I am trying to do something simple like lambda expressions in Boost.LambdaLib (may be, I am on a wrong way):

sort(some_vector.begin(), some_vector.end(), _1 < _2)

I did this:

template<typename T>
bool my_func_greater (const T& a, const T& b) {
  return a > b;
}

template<typename T>
bool my_func_lesser (const T& a, const T& b) {
  return b > a;
}

class my_comparing {
 public:
  int value;
  my_comparing(int value) : value(value) {}
  template <typename T>
  bool (*operator<(const my_comparing& another) const)(const T&, const T&) {
    if (this->value == 1 && another.value == 2) {
      return my_func_greater<T>;
    } else {
      return my_func_greater<T>;
    }
  }
};

const my_comparing& m_1 = my_comparing(1);
const my_comparing& m_2 = my_comparing(2);

It works:

sort(a, a + 5, m_1.operator< <int>(m_2));

But I want that it doesn't require template argument as in LambdaLib.

like image 965
Programmer585 Avatar asked Dec 14 '11 09:12

Programmer585


People also ask

What is template argument deduction?

Template argument deduction is used in declarations of functions, when deducing the meaning of the auto specifier in the function's return type, from the return statement.

What is type deduction?

Type inference or deduction refers to the automatic detection of the data type of an expression in a programming language. It is a feature present in some strongly statically typed languages. In C++, the auto keyword(added in C++ 11) is used for automatic type deduction.

What is CTAD C++?

Class Template Argument Deduction (CTAD) is a C++17 Core Language feature that reduces code verbosity. C++17's Standard Library also supports CTAD, so after upgrading your toolset, you can take advantage of this new feature when using STL types like std::pair and std::vector.


1 Answers

Deduction from return type is not possible. So function2 can't be deduced from what return type you expect.

It is however possible to deduce cast operator. So you can replace function2 with a helper structure like: Unfortunately there is no standard syntax for declaring cast operator to function pointer without typedef and type deduction won't work through typedef. Following definition works in some compilers (works in G++ 4.5, does not work in VC++ 9):

struct function2 {
    template <typename T>
    (*operator bool())(T) {
        return function1<T>;
    }
};

(see also C++ Conversion operator for converting to function pointer).

The call should than still look the same.

Note: C++11 introduces alternative typedef syntax which can be templated. It would be like:

struct function2 {
    template <typename T>
    using ftype = bool(*)(T);

    template <typename T>
    operator ftype<T>() {
        return function1<T>;
    }
};

but I have neither G++ 4.7 nor VC++ 10 at hand, so I can't test whether it actually works.


Ad Added:

The trick in Boost.Lambda is that it does not return functions, but functors. And functors can be class templates. So you'd have:

template<typename T>
bool function1(T some_var) { return true; }

class function2 {
    template <typename T>
    bool operator()(T t) {
        function1<T>;
    }
};

template <typename F>
void function3( F input_function ) { ... input_function(something) ... }

Now you can write:

function3(function2);

and it's going to resolve the template inside function3. All STL takes functors as templates, so that's going to work with all STL.

However if don't want to have function3 as a template, there is still a way. Unlike function pointer, the std::function (C++11 only, use boost::function for older compilers) template can be constructed from any functor (which includes plain function pointers). So given the above, you can write:

void function3(std::function<bool ()(char)> input_function) { ... input_function(something) ... }

and now you can still call:

function3(function2());

The point is that std::function has a template constructor that internally generates a template wrapper and stores a pointer to it's method, which is than callable without further templates.

like image 130
Jan Hudec Avatar answered Sep 21 '22 22:09

Jan Hudec