Abe*_*der 2 c++ operators type-traits c++11
我需要检查给定的类是否<<(cls, ostream)
定义了运算符.如果是这样,我希望我的函数使用它来写入ostringstream
,否则应该使用样板代码.
我知道之前已经问过这个问题.但是,我通常会发现自定义解决方案并不总是适用于我的编译器(clang ++).经过几个小时的搜索,我终于发现了boost :: type_traits.我之前没有看过那里,因为我假设c ++ 11已经复制了特征部门的所有内容.
对我有用的解决方案是:
template <typename C>
std::string toString(C &instance) {
std::ostringstream out;
out << to_string<C, boost::has_left_shift<C, std::ostream>::value>::convert(ctx);
return out.str();
}
Run Code Online (Sandbox Code Playgroud)
以to_string
定义为:
template <typename C, bool>
struct to_string {
// will never get called
static std::string convert(LuaContext &ctx) {}
};
template <typename C>
struct to_string<C, true> {
static std::string convert(LuaContext &ctx) {
return "convert(true) called.";
}
};
template <typename C>
struct to_string<C, false> {
static std::string convert(LuaContext &ctx) {
return "convert(false) called.";
}
};
Run Code Online (Sandbox Code Playgroud)
所以我发布这个有两个原因:
检查这是否是最安全的使用方法,或者看看其他人是否可以建议更好的解决方案(即问题更多的是出于对方法的好奇而不是"这会起作用吗?" - 它已经适用于我)
发布这个以节省其他人的搜索时间,以防他/他也需要做类似的事情.
作为一个更普遍的问题 - 有时trait类似乎返回std :: true_type或std :: false_type(好吧,至少对于非boost类).其他时候他们是bool.这种差异是否有原因?如果boost:has_left_shift
返回一个类型而不是一个bool
,那么我可以只有一个to_string
结构.
快速而肮脏的C++ 11 SFINAE:
template<typename T,
typename = decltype(
std::declval<std::ostream&>() << std::declval<T const&>()
)
>
std::string toString(T const& t)
{
std::ostringstream out;
// Beware of no error checking here
out << t;
return out.str();
}
template<typename T,
typename... Ignored
>
std::string toString(T const& t, Ignored const&..., ...)
{
static_assert( sizeof...(Ignored) == 0
, "Incorrect usage: only one parameter allowed" );
/* handle any which way here */
}
Run Code Online (Sandbox Code Playgroud)
如果你想要你也可以检查返回类型stream << val
确实可以转换为std::ostream&
:
template<typename T,
typename Result = decltype(
std::declval<std::ostream&>() << std::declval<T const&>()
),
typename std::enable_if<
std::is_convertible<Result, std::ostream&>::value,
int
>::type = 0
>
Run Code Online (Sandbox Code Playgroud)
至于一个不那么快速和肮脏的解决方案,我会引入一个is_stream_insertable
特性,该实现可以利用这里使用的相同技巧.
请注意,std::integral_constant<bool, B>
有一个转换运算符bool
,这可能会解释您观察到的一些事情.我也不建议将C++ 11 Standard类型和特性与Boost混合std::true_type
使用:不要混淆boost::true_type
!这并不是说您不应该使用例如Boost.TypeTraits与C++ 11,但尝试保持一致,并且一次只使用两个中的一个.
归档时间: |
|
查看次数: |
1719 次 |
最近记录: |