__has_include
,它可以[make]从实验迁移到std几乎是无缝的
这仍然存在如何做的问题。像
namespace std { using namespace std::experimental; }
这样的操作是不确定的行为,所以我想出了以下方法:optional.h在coliru上的演示
#pragma once
#if __has_include(<optional>)
# include <optional>
# define HAS_STD_OPTIONAL
#elif __has_include(<experimental/optional>)
# include <experimental/optional>
# define HAS_STD_EXPERIMENTAL_OPTIONAL
#else
# error Must have an optional type, either from <optional> or if not supported from <experimental/optional>.
#endif
#if defined HAS_STD_OPTIONAL
namespace opt {
template<class T>
using optional = std::optional<T>;
using bad_optional_access = std::bad_optional_access;
using nullopt_t = std::nullopt_t;
using in_place_t = std::in_place_t;
constexpr auto nullopt = std::nullopt;
constexpr auto in_place = std::in_place;
template<class T>
constexpr auto make_optional(T && value)
{
return std::make_optional(std::forward<T>(value));
}
}
#elif defined HAS_STD_EXPERIMENTAL_OPTIONAL
namespace opt {
template<class T>
using optional = std::experimental::optional<T>;
using bad_optional_access = std::experimental::bad_optional_access;
using nullopt_t = std::experimental::nullopt_t;
using in_place_t = std::experimental::in_place_t;
constexpr auto nullopt = std::experimental::nullopt;
constexpr auto in_place = std::experimental::in_place;
template<class T>
constexpr auto make_optional(T && value)
{
return std::experimental::make_optional(std::forward<T>(value));
}
}
#endif
#1 楼
@Jerry答案的修改:#pragma once
#if __has_include(<optional>)
# include <optional>
namespace stdx {
using namespace ::std;
}
#elif __has_include(<experimental/optional>)
# include <experimental/optional>
namespace stdx {
using namespace ::std;
using namespace ::std::experimental;
}
#else
# error <experimental/optional> and <optional> not found
#endif
这具有以下优点:同一命名空间可用于所有“实验”功能(
stdx
)。所以
stdx::optional
和stdx::variant
都可以。程序不良。#2 楼
尽管对它们的操作有一定的限制(有时很烦人),但乍看之下它们似乎不适用于此处,因此我至少尝试使用名称空间别名:#pragma once
#if __has_include(<optional>)
# include <optional>
using namespace opt = std;
#elif __has_include(<experimental/optional>)
# include <experimental/optional>
using namespace opt = std::experimental;
#else
# error Must have an optional type, either from <optional> or if not supported from <experimental/optional>.
#endif
然后从这一点开始,您只需使用:
opt::whatever
,然后视情况将其映射到std::whatever
或std::experimental::whatever
。评论
\ $ \ begingroup \ $
* facepalm *。这就是为什么我需要代码审查
\ $ \ endgroup \ $
–贾斯汀
16年7月29日在23:59
\ $ \ begingroup \ $
如果我尝试使用std :: optional以外的其他实验类型,这不会引起问题吗? opt :: any ...似乎有点怪异,我猜然后名称空间应该确实是stdext或类似的东西。
\ $ \ endgroup \ $
–贾斯汀
16年7月30日在0:02
\ $ \ begingroup \ $
@Justin:是的,您可能从我最初发布的内容中可以猜到,我首先使用名称空间stdex = ...,然后(部分地)将其切换为使用问题中的opt。您可以很好地定义stdext(或其他)和opt,并在适当时使用它们(即使它们在本质上是彼此同义的)。不太确定后者是否是一个好主意。
\ $ \ endgroup \ $
–杰里·科芬(Jerry Coffin)
16 Jul 30'0:07
\ $ \ begingroup \ $
名称空间stdx {使用名称空间:: std;使用命名空间:: std :: experimental; }可以,不是吗?
\ $ \ endgroup \ $
– ak牛
16年7月30日在1:27
\ $ \ begingroup \ $
@Yakk这将要求同时定义std和std :: experimental,但我不明白为什么这样不起作用:命名空间std {命名空间实验性{}}命名空间stdx使用命名空间std :: experimental; }。想知道std和std :: experimental之间是否有任何冲突。
\ $ \ endgroup \ $
–贾斯汀
16年7月30日在1:54
#3 楼
与其他答案类似,但只是可选的,而没有引入其余的std :: experimental。顺便说一下,我们在真实的代码库中使用了此代码:#pragma once
#if __has_include(<optional>)
#include <optional>
namespace stdx {
using std::optional;
using std::nullopt_t;
using std::in_place_t;
using std::bad_optional_access;
using std::nullopt;
using std::in_place;
using std::make_optional;
}
#elif __has_include(<experimental/optional>)
#include <experimental/optional>
namespace stdx {
using std::experimental::optional;
using std::experimental::nullopt_t;
using std::experimental::in_place_t;
using std::experimental::bad_optional_access;
using std::experimental::nullopt;
using std::experimental::in_place;
using std::experimental::make_optional;
}
#else
#error "an implementation of optional is required!"
#endif
评论
\ $ \ begingroup \ $
为什么要使用命名空间:: std;在第二种情况下(使用
\ $ \ endgroup \ $
–贾斯汀
16 Jul 30'2:09
\ $ \ begingroup \ $
@justin因为我想最大程度地减少实验性/可选性与不存在的情况之间的差异。为什么以::为前缀?如果有名称空间std :: std或std :: experimental :: std或其他名称:我想保持明确。否则使用命名空间std;在使用命名空间std之后;可能使用std :: std,这是意外的。我们正在做奇怪的魔咒,我会变得偏执。
\ $ \ endgroup \ $
– ak牛
16年7月30日在2:21