请考虑以下代码:
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那样的模板参数。
答案 0 :(得分:5)
编译器不使用表达式上下文来推断其模板参数。对于编译器,function3(function2());
看起来像
auto tmp = function2();
function3(tmp);
它不知道function2
模板参数是什么。
答案 1 :(得分:5)
无法从退货类型中扣除。因此,function2
无法从您期望的返回类型中推断出来。
然而,可以推导出演员。 所以你可以用一个辅助结构替换不幸的是,没有标准语法用于在没有typedef的情况下将转换操作符声明为函数指针,并且类型推导不能通过typedef工作。以下定义适用于某些编译器(适用于G ++ 4.5,在VC ++ 9中不起作用):function2
,如:
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;
我知道这很简单,每个人都知道这一点。没有人发布这个,我想试一试。