[英]How to call templated type with
I am trying to create a template function that has two different implementations based on a template argument. 我正在尝试创建一个模板函数,它具有两个基于模板参数的不同实现。 While the first one is specific for I/O manipulators and the second one is for any general case.
第一个是针对I / O操纵器的,第二个针对任何一般情况。
template <typename T>
typename std::enable_if<
std::is_same<decltype(std::setw), T>::value>::type
foo(T& t){
cout << "enabled" << std::endl;
}
template <typename T>
void foo(T& t){
cout << "Normal" << std::endl;
}
template <typename... Ts>
void foohelper(Ts... t){
foo(t...);
}
int main(){
foohelper(std::setprecision(3)); // It should print enabled, but printing Normal
}
Currently it is not doing what I am trying to implement. 目前它没有做我想要实现的。 How can I fix it?
我该如何解决?
You don't need to use enable_if
- just specialise the template below the main definition of template foo
. 您不需要使用
enable_if
- 只需在template foo
的主要定义下面专门化template foo
。
template <>
void foo<decltype(std::setw(0))>(decltype(std::setw(0))& t)
{
cout << "enabled" << std::endl;
}
The return type of these functions are unspecified . 这些函数的返回类型未指定 。 That means you can't use
type_traits
to compare them. 这意味着你不能使用
type_traits
来比较它们。 As an example, here's libcxx
: 举个例子,这是
libcxx
:
// Definitions omitted
T2 setiosflags (ios_base::fmtflags mask);
T3 setbase(int base);
template<charT> T4 setfill(charT c);
T5 setprecision(int n);
T6 setw(int n);
T5
, T6
, etc. refer to __imo_t4
etc., an internal structure that does the actual work of the manipulator. T5
, T6
等指的是__imo_t4
等,它是执行机械手实际工作的内部结构。 Since they all have different return types, the functions have different types. 由于它们都具有不同的返回类型,因此功能具有不同的类型。 Hence they'll all be different.
因此他们都会有所不同。
You can use SFINAE by comparing the return type of the function std::setprecision
. 您可以通过比较函数
std::setprecision
的返回类型来使用SFINAE。 Since the return type is unspecified, you will need decltype
and std::declval
. 由于返回类型未指定,因此您需要
decltype
和std::declval
。
Here's the solution: 这是解决方案:
template <typename T, typename std::enable_if<std::is_same<decltype(std::setprecision(std::declval<int>())), typename std::decay<T>::type>::value, int>::type = 0>
void foo(T&& t) {
cout << "enabled" << std::endl;
}
Here I changed T&
to T&&
so it accept any kind of reference. 在这里,我将
T&
改为T&&
因此它接受任何类型的参考。 That remove the use of your foohelper
. 删除你的
foohelper
的使用。
Furthermore, is the type comparison, I decay the type T
, since the comparison won't work if one of the type is a reference type, because T&
is not the same as T
. 此外,是类型比较,我衰减类型
T
,因为如果其中一个类型是引用类型,则比较将不起作用,因为T&
与T
。 The use of std::decay
will effectively remove the reference. 使用
std::decay
将有效地删除引用。
Notice that I moved the SFINAE construct inside the template declaration. 请注意,我在模板声明中移动了SFINAE构造。 This is to keep SFINAE away from the return type.
这是为了使SFINAE远离返回类型。 The use of non type template parameter defaulted to
0
won't affect the use of the function and will ensure that no one can effectively bypass the SFINAE check. 使用默认为
0
的非类型模板参数不会影响函数的使用,并且将确保没有人能够有效地绕过SFINAE检查。
Edit: 编辑:
You can replace std::declval<int>()
with 0
in your case. 在您的情况下,您可以将
std::declval<int>()
替换为0
。 I was just willing to show how you can use this tool to replace actual value. 我只是愿意展示如何使用这个工具来取代实际价值。 There are a lot of cases where you can't have values.
在很多情况下你不能拥有价值观。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.