扣除模板参数C ++

时间:2011-12-14 09:19:30

标签: c++ templates

请考虑以下代码:

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) ) {}

如果我打电话

function3(function2<char>());

没关系。但如果我打电话

function3(function2());

编译器给出的错误是它无法推导模板的参数。

请问,你可以建议(提出一个想法)如何重写function1和/或function2(可能,从根本上说是使用类重写)来使它好吗?

*已添加*

我正在尝试做一些简单的事情,比如Boost.LambdaLib中的lambda表达式(可能是,我的方法不对):

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

我这样做了:

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

有效:

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

但我希望它不需要像LambdaLib那样的模板参数。

4 个答案:

答案 0 :(得分:5)

编译器不使用表达式上下文来推断其模板参数。对于编译器,function3(function2());看起来像

auto tmp = function2();
function3(tmp);

它不知道function2模板参数是什么。

答案 1 :(得分:5)

无法从退货类型中扣除。因此,function2无法从您期望的返回类型中推断出来。

然而,可以推导出演员。 所以你可以用一个辅助结构替换function2,如:不幸的是,没有标准语法用于在没有typedef的情况下将转换操作符声明为函数指针,并且类型推导不能通过typedef工作。以下定义适用于某些编译器(适用于G ++ 4.5,在VC ++ 9中不起作用):

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

(另见C++ Conversion operator for converting to function pointer)。

呼叫应该看起来仍然相同。

注意:C ++ 11引入了可以模板化的替代typedef语法。这就像是:

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

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

但我既没有G ++ 4.7也没有VC ++ 10,所以我无法测试它是否真的有效。


广告已添加:

Boost.Lambda中的技巧是它不返回函数,而是函数。而仿函数可以是类模板。所以你有:

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) ... }

现在你可以写:

function3(function2);

它将解析function3内的模板。所有STL都将仿函数作为模板,因此可以使用所有STL。

但是,如果不想将function3作为模板,仍有办法。与函数指针不同,std::function(仅适用于C ++ 11,对较旧的编译器使用boost::function)模板可以从任何函子(包括普通函数指针)构造。因此,如上所述,您可以写:

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

现在你仍然可以打电话:

function3(function2());

关键是std::function有一个模板构造函数,它在内部生成一个模板包装器并存储一个指向它的方法的指针,该方法可以在没有其他模板的情况下调用。

答案 2 :(得分:2)

编辑完成后,我认为您想要做的事情可以更简单。请参阅以下类型:

struct Cmp {
  bool const reverse;
  Cmp(bool reverse) : reverse(reverse) {}
  template <typename T> bool operator()(T a, T b) {
    return reverse != (a < b);
  }
};

现在,在您的operator<中,根据参数的顺序返回无类型 Cmp实例,即m_2 < m_1将返回Cmp(true)m_1 < m_2将返回Cmp(false)

由于存在模板operator(),编译器将在sort内推断出正确的功能,而不是在sort的调用中。

答案 3 :(得分:1)

我不确定这对你有帮助,而且我不是这方面的专家。我从昨天起就一直在看这篇文章,我想参加这个。

模板无法推断出它的类型,因为编译器不知道您希望返回的类型。以下是一个类似于function2()的简单示例。

template<typename T>
T foo() {
    T t;
    return t;
};

调用此函数

foo(); // no type specified. T cannot be deduced.

是否可以将模板声明移动到类级别,如下所示:

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

template <typename T>
class my_comparing {
public:
    int value;
    my_comparing(int value) : value(value) {}
    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>;
        }
    }
};

并声明m_1和m_2如下:

const my_comparing<int>& m_1 = my_comparing<int>(1);
const my_comparing<int>& m_2 = my_comparing<int>(2);

现在您可以按如下方式进行比较:

if( m_1 < m_2 )
    cout << "m_1 is less than m_2" << endl;
else
    cout << "m_1 is greater than m_2" << endl;

我知道这很简单,每个人都知道这一点。没有人发布这个,我想试一试。