我想为类型和函数编写MP预测器。似乎有些事情是非法的:
#include <iostream>
template <class R>
struct X {
static constexpr int value = 0;
};
// Specialization for type
template <>
struct X<int(int)> {
static constexpr int value = 1;
};
// ERROR: Redefinition with diffrent kind
template <int (*F)(int)>
struct X {
static constexpr int value = 2;
};
int fun(int);
int main(int, char* [])
{
std::cout << "X<int>: " << X<int>::value << '\n';
std::cout << "X<int(int)>: " << X<int(int)>::value << '\n';
std::cout << "X<decltype(fun)>: " << X<decltype(fun)>::value << '\n';
std::cout << "X<fun>: " << X<fun>::value << '\n';
return 0;
}
是否有可能实现这样的目标?
更多细节: 为什么?
答案 0 :(得分:2)
是否有可能实现这样的目标?
您有效地询问的是您是否可以重载类模板。你不能。
但是,你当然可以重载函数模板 - 你可以有一个函数模板,它接受一个非推导的模板类型参数,专门化它,然后有另一个函数模板,它接受一个非推导模板非类型参数:< / p>
#include <iostream>
template <class R> constexpr int X() { return 0; }
// specialization for type
template <> constexpr int X<int(int)>() { return 1; }
// Redefinition with different kind
template <int (*F)(int)>
constexpr int X() { return 2; }
int fun(int);
int main(int, char* [])
{
std::cout << "X<int>: " << X<int>() << std::endl;
std::cout << "X<int(int)>: " << X<int(int)>() << std::endl;
std::cout << "X<decltype(fun)>: " << X<decltype(fun)>() << std::endl;
std::cout << "X<fun>: " << X<fun>() << std::endl;
return 0;
}
根据需要打印0,1,1和2。
答案 1 :(得分:0)
我认为这是不可能的。 template参数只能是类型或值。在声明中:
template <class R>
struct X {
static constexpr int value = 0;
};
指定X以将类型作为参数。
// ERROR: Redefinition with diffrent kind
template <int (*F)(int)>
struct X {
static constexpr int value = 2;
};
您想要专门化X来获取值(函数指针)。这确实与你首先声明了X.因此你得到了重新定义错误。
如果您想以更一般的方式实现预测器,则必须使用SFINAE模式。我在过去写了类似的东西,但放弃了它,因为它使用起来太笨拙而容易出错。我不太记得,但我想我发现了一些不成功的案例。出于教育目的,我在这里发布代码:
#include <type_traits>
#include <iostream>
namespace Detail {
template <
class Function,
class Result,
class Enable,
class... Args
>
struct isFunctionImpl {
static constexpr bool value = false;
};
template <
class Function,
class Result,
class... Arg
>
struct isFunctionImpl <
Function,
Result,
typename std::enable_if<
std::is_same<
Result,
decltype(std::declval<Function>()(*reinterpret_cast<Arg*>(0)...))
>::value
>::type,
Arg...
> {
static constexpr bool value = true;
};
} // End of namespace Detail
template <
class Function,
class Result,
class... Args
>
struct isFunction {
static constexpr bool value = Detail::isFunctionImpl<Function, Result, void, Args...>::value;
};
int foo(int bar) {
return 0;
}
int main() {
std::cout << "Is function " << isFunction<decltype(foo), int, int>::value << std::endl;
std::cout << "Is function " << isFunction<decltype(foo), int, std::string>::value << std::endl;
}