检查type是否可以作为boost :: lexical_cast <string>的参数

Pra*_*han 5 c++ templates boost template-meta-programming c++11

我有以下traits class(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;
}
Run Code Online (Sandbox Code Playgroud)

此程序打印1,但lexical_cast<string>(a)导致编译错误.什么是正确的实施方式IsLexCastable?

(这是用g++48 -std=c++11和编译的boost 1.55.0.)

Col*_*mbo 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 {};
Run Code Online (Sandbox Code Playgroud)

演示.
该要求被称为 OutputStreamable由文档,和施加到源类型的直接之一.


为什么你的实现不起作用?

decltype只会导致函数模板声明的实例化.内部静态断言在定义中被触发lexical_cast,因此它不能在SFINAE中使用.

[temp.inst]/10:

如果以涉及重载解析的方式使用函数模板或成员函数模板特 化,则隐式实例化特化的声明(14.8.3).

  • @NirFriedman这不是一些实现细节,而是库强加的实际要求. (3认同)
  • 这段代码可能有用,但它的设计实际上比OP的代码更糟糕,因为你正在使用boost :: lexical_cast的实现细节.如果你想走这条路线,你也可以在不合适的类型上使用它时复制并粘贴boost :: lexical_cast中失败的静态断言.我们的想法是让代码告诉boost :: lexical_cast是否可以工作,无论它是如何实现的. (2认同)
  • @Pradhan SFINAE仅适用于直接环境.调用`boost :: lexical_cast <std :: string>(std :: declval <T>())`在直接上下文中完美地形成,因为有这样的函数模板.在实例化时该函数模板是否实际编译无关紧要. (2认同)