我有以下特征类(IsLexCastable
)来检查是否可以通过调用boost::lexical_cast<string>
将类型转换为字符串。它错误地为true
返回vector<int>
。
#include <iostream>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
namespace std
{
/// Adding to std since these are going to be part of it in C++14.
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
}
template <typename T, typename = void>
struct IsLexCastable : std::false_type
{
};
template <typename T>
struct IsLexCastable<T, std::enable_if_t<std::is_same<std::string, decltype(boost::lexical_cast<std::string>(std::declval<T>()))>::value> > : std::true_type
{
};
int main()
{
vector<int> a = {1, 2, 3};
// cout << lexical_cast<string>(a) << endl;
cout << IsLexCastable<decltype(a)>::value << endl;
return 0;
}
此程序打印1
,但lexical_cast<string>(a)
会导致编译错误。实施IsLexCastable
的正确方法是什么?
(这是使用g++48 -std=c++11
和boost 1.55.0
编译的。)
答案 0 :(得分:5)
您的表达式还不够,因为lexical_cast
功能模板会占用所有内容,并且只会通过内部static_assert
报告错误。而是测试将对象插入std::ostream
是否有效:
template <typename T, typename=void>
struct IsLexCastable : std::false_type {};
// Can be extended to consider std::wostream as well for completeness
template <typename T>
struct IsLexCastable<T,
decltype(void(std::declval<std::ostream&>() << std::declval<T>()))>
: std::true_type {};
Demo。
该要求被the documentation称为 OutputStreamable ,而直接强加于源类型。
<小时/>
decltype
仅导致函数模板的实例化。内部静态断言在lexical_cast
的定义内触发,因此不能在SFINAE中使用。
[temp.inst] / 10:
如果是功能模板或成员函数模板专门化 以涉及重载解析的方式使用,专门化的声明被隐式实例化(14.8.3)。
答案 1 :(得分:0)
Columbo的回答回答了这个问题,但我在适应输入流方面遇到了问题。我的用例是我想调用lexical_cast从字符串转换为T. Boost提供has_right_shift和has_left_shift,它可以为类似的结构提供更多的灵活性。
template <typename T, typename=void>
struct IsLexCastable : std::false_type {};
template <typename T>
struct IsLexCastable<T,
typename std::enable_if<boost::has_right_shift<T>::value>::type>
: std::true_type {};