所以,我有this templatized function(我知道是丑陋看。)有没有办法为Templatized函数声明一个typename?
我的目的不是为了虽然默认模板参数,我的意图是要建立一个typename
从T
可能在caster
使用推导出用户无法分配给。
我的问题是如何为模板化函数创建一个typename
用户无法将其作为参数传递?
举个例子:
显然,这段代码不能编译,但是这就是我想实现的行为。是否是函子唯一的方法来做到这一点?
所以,我有this templatized function(我知道是丑陋看。)有没有办法为Templatized函数声明一个typename?
我的目的不是为了虽然默认模板参数,我的意图是要建立一个typename
从T
可能在caster
使用推导出用户无法分配给。
我的问题是如何为模板化函数创建一个typename
用户无法将其作为参数传递?
举个例子:
显然,这段代码不能编译,但是这就是我想实现的行为。是否是函子唯一的方法来做到这一点?
在C++ 14中,使用返回类型推导优雅地解决了这个问题。
// C++14
#include <type_traits>
template <typename T>
decltype(auto)
foo(T bar)
{
using R = std::conditional_t<sizeof(T) == 4, char, short>;
return static_cast<R>(bar);
}
在C++ 11中,您必须重复类型计算。
// C++11
#include <type_traits>
template <typename T>
typename std::conditional<sizeof(T) == 4, char, short>::type
foo(T bar)
{
using R = typename std::conditional<sizeof(T) == 4, char, short>::type;
return static_cast<R>(bar);
}
这可以通过使用decltype
找出类型来缩短一点。
// C++11
#include <type_traits>
template <typename T>
typename std::conditional<sizeof(T) == 4, char, short>::type
foo(T bar)
{
using R = decltype(foo(bar));
return static_cast<R>(bar);
}
但坦率地说,使用简单的默认类型参数有什么问题?
// C++11
#include <type_traits>
template <typename T,
typename R = typename std::conditional<sizeof(T) == 4, char, short>::type>
R
foo(T bar)
{
return static_cast<R>(bar);
}
请注意,我已经更换的R
值初始化你return
语句和static_cast
沉默编译器警告有关收缩转换。但你确定这是你想要的吗?
一种可能性是使用using
类型别名而不是typename
。下面的代码在我测试的编译器上编译(记得启用-std=c++11
标志)。
#include <type_traits>
#include <iostream>
// C++11
template <typename T>
using R = typename std::conditional<sizeof(T) == 4, char, short>::type;
template <typename T>
R<T> foo(T bar){return R<T>(bar);}
int main() {
std::cout << foo(13.0) << std::endl;
return 0;
}
在C++ 14中,您可以使用conditional_t
特征,这更简单。
// C++14
template <typename T>
using R = std::conditional_t<sizeof(T) == 4, char, short>;
它可以工作,但我不太喜欢这个解决方案,因为它引入了一个新的全局名称。如果这个'R'模板本身是有用的,那么这是一个很好的解决方案,但如果只是用函数声明保存一些输入,我就不愿意全局引入一个新的类型名称。绝对不是有这样一个共同/简称的人。将助手类型放入其自己的名称空间可以帮助缓解问题。 – 5gon12eder 2015-02-23 19:05:38
@YingXiong我无法得到这个工作在Visual Studio 2013或gcc 4.92。测试代码应该失败:'std :: cout << foo(13.0)<< std :: endl;''gcc说:“错误:无法绑定'std :: ostream {aka std :: basic_ostream
@JonathanMee您说得对,我之前没有编译过您的测试用例,对不起。我更新我的答案以解决问题 - 基本上你应该使用'std :: conditional'特征的':: type',而不是特征本身。请同时注意@ 5gon12eder的评论,我完全同意。 – 2015-02-23 20:23:10
@JonathanMee自C++ 11以来,你可以使用'template auto foo(T t,U u) - > decltype(t + u){return t + u; }'。这是一个*尾随返回类型*,但没有*返回类型扣除*。由于C++ 14,你也可以使用'template decltype(auto)foo(T t,U u){return t + u; }'这仅仅是语法糖,但对于减少冗余非常有用。 –
5gon12eder
2015-02-23 18:45:04