模板参数默认为更高版本
Template parameter default to a later one
这个链接没有回答我的问题,所以我会在这里问:
基本上我想写一个模板函数
template <typename Out, typename In>
Out f(In x);
在这里,我在调用f
时总是需要指定Out
。 我不想每次都这样做,所以我基本上想要
template <typename Out = In, typename In>
Out f(In x);
这意味着如果我不指定Out
,它将默认为 In
。 但是,这在 C++11 中是不可能的。
所以我的问题是,有没有办法达到效果:
- 调用
f(t)
将实例化f<T,T>(t)
或更一般的f<typename SomeThing<T>::type, T>
- 调用
f<U>(t)
将实例化f<U, T>(t)
您可能永远不想指定In
而是推断它,对吧?
在这种情况下,您需要重载函数:
template <typename Out, In>
Out f(In x);
template <typename T>
T f(T x);
称之为:
f(42);
f<float>(42);
。但不幸的是,这对f<int>(42)
来说是模棱两可的.无论如何,我们都可以使用 SFINAE 来适当地禁用其中一个重载:
template <
typename Out,
typename In,
typename = typename std::enable_if<not std::is_same<Out, In>::value>::type
>
Out f(In x);
template <typename T>
T f(T x);
为了避免实现中的冗余,让两个函数调度到一个共同的实现,f_impl
。
下面是一个工作示例:
template <typename Out, typename In>
Out f_impl(In x) {
std::cout << "f<" << typeid(Out).name() <<
", " << typeid(In).name() <<
">(" << x << ")n";
return x;
}
template <
typename Out,
typename In,
typename = typename std::enable_if<not std::is_same<Out, In>::value>::type
>
Out f(In x) {
std::cout << "f<Out, In>(x):t ";
return f_impl<Out, In>(x);
}
template <typename T>
T f(T x) {
std::cout << "f<T>(x):t ";
return f_impl<T, T>(x);
}
int main() {
f(42);
f<float>(42);
f<int>(42);
}
这里可能不需要它,但这里有一个经典的技术:
struct Default
{
template <typename Argument, typename Value>
struct Get {
typedef Argument type;
};
template <typename Value>
struct Get <Default, Value> {
typedef Value type;
};
};
template <typename Out = Default, typename In>
typename Default::Get<Out, In>::type f(In x);
我这里有一个完美的解决方案! f<const int&>
不起作用,因为函数无法返回对临时的引用,与此处使用的技术无关。
[hidden]$ cat a.cpp
#include <iostream>
#include <type_traits>
#include <typeinfo>
using namespace std;
template <typename Out, typename In>
Out f_impl(In x) {
cout << "Out=" << typeid(Out).name() << " " << "In=" << typeid(In).name() << endl;
return Out();
}
template <typename T, typename... Args>
struct FirstOf {
typedef T type;
};
template <typename T, typename U>
struct SecondOf {
typedef U type;
};
template <typename... Args, typename In>
typename enable_if<sizeof...(Args) <= 1, typename FirstOf<Args..., In>::type>::type f(In x) {
typedef typename FirstOf<Args..., In>::type Out;
return f_impl<Out, In>(x);
}
template <typename... Args, typename In>
typename enable_if<sizeof...(Args) == 2, typename FirstOf<Args...>::type>::type f(In x) {
typedef typename FirstOf<Args...>::type Out;
typedef typename SecondOf<Args...>::type RealIn;
return f_impl<Out, RealIn>(x);
}
int main() {
f(1);
f(1.0);
f<double>(1);
f<int>(1.0);
f<int>(1);
f<const int>(1);
f<int, double>(1);
f<int, int>(1);
f<double, double>(1);
}
[hidden]$ g++ -std=c++11 a.cpp
[hidden]$ ./a.out
Out=i In=i
Out=d In=d
Out=d In=i
Out=i In=d
Out=i In=i
Out=i In=i
Out=i In=d
Out=i In=i
Out=d In=d
相关文章:
- 在 C++11 及更高版本中,有没有办法初始化初始值设定项列表中的向量?
- 如何获得CMake Tools以在Visual Studio Code中编译具有C++11(或更高版本)功能的程序?
- 如何将_RICHEDIT_VER(riched20.dll)升级到版本3或更高版本
- 在 Visual Studio 2010(及更高版本)中定义包含或链接路径变量的位置
- C++14 及更高版本是否允许 Lambda 函数的默认参数?如果是这样,怎么办?
- 片段着色器中的"错误:在 GLSL 1.30 及更高版本中禁止使用非常量表达式索引的采样器数组"
- 在Mac OS X Mountain Lion(或更高版本)和Linux上使用X11/Xlib.h
- 对于我在 Microsoft Visual C++ IDE (2005 或更高版本)的本机 win32 项目中编写的应用
- 将用户输入绑定到UE4.22.3及更高版本中的UActorComponent方法
- 使用 C++17 或更高版本对向量中的元素对求和的最'functional'方法?
- 在C 11或更高版本中,是否可以通过Lambda来实现单方法纯Virtual C 接口
- 是 GCC 6.2 或更高版本中的 C++20 实验范围
- 如何在 CMake 3.7 及更高版本中表达 PGO 依赖项
- C++11及更高版本:shared_ptr,用于管理由低级C库提供的系统资源
- 如何在 CMake 目标上请求 C++11 或更高版本
- 如何在Windows和更高版本上保留内存,并将文件映射到内存中
- 谁能帮助我在 4.0 及更高版本上实现 Android Blur,而无需学习 Renderscript
- 如何使用Windows Server 2003及更高版本上的虚拟磁盘服务(VDS)登录ISCSI目标
- 区分 VC++ 2010 和更高版本的编译器版本
- flens lapack:需要GNU GCC 4.7版或更高版本!我的mac有