我想测试一个类型是否可以传递给某个函数,但我想在函数查找上使用 ADL 并包含来自某个命名空间的函数。
考虑这段代码:
#include <utility>
#include <vector>
template<class T>
concept Swappable = requires(T& a, T& b)
{
swap(a,b);
};
static_assert(Swappable<std::vector<int>>); // #1
static_assert(Swappable<int>); // #2
Run Code Online (Sandbox Code Playgroud)
#1 成功,它发现std::swap
becausestd
是 的关联命名空间std::vector<int>
。但 #2 失败了,内置类型没有关联的命名空间。
我该怎么写这样的东西:
template<class T>
concept Swappable = requires(T& a, T& b)
{
using std::swap; // illegal
swap(a,b);
};
Run Code Online (Sandbox Code Playgroud)
AFAIK,您不允许在 require 表达式中使用 using 声明。
(注意,虽然对此有一个完美的标准 C++ 概念,但std::swappable
此示例swap
仅用于说明。我并不是特别想测试某些东西是否实际上是可交换的,我只是想找到一种方法来实现这样的概念其中自定义函数在已知命名空间中具有默认实现,但可能在关联的命名空间中具有重载。)
编辑作为一种解决方法,我可以在一个单独的名称空间中实现这个概念,其中的名称被拉入。对此不太满意,但它有效。
namespace detail
{
using std::swap;
template<class T>
concept Swappable = …
Run Code Online (Sandbox Code Playgroud) 我有一个类似容器的类,如果底层类型是仅移动的,我只想移动,否则可以复制.为简单起见,我们假设可复制性由单个bool模板参数决定:
template<bool IsCopyable>
struct Foo
{
Foo();
Foo(const Foo&); // only include this when IsCopyable is true
Foo(Foo&&);
Foo& operator=(const Foo&); // only when IsCopyable
Foo& operator=(Foo&&);
};
Run Code Online (Sandbox Code Playgroud)
现在,我不能只是SFINAE复制ctor,因为这需要使它模板化,模板化的功能不能复制ctor.另外,我不能只static_assert()
在拷贝ctor中做一个.虽然这会捕获复制文件的错误用法,但它也使该类固有地从外部复制可构造(std::is_copy_constructible
类型特征将产生真实).
顺便说一句,一个不幸的要求是它需要在VC++ 2012中编译,所以我不能使用花哨的表达式SFINAE,继承ctors,默认/删除函数或constexpr if
(尽管如此,如果你有一个简洁的C++解决方案17我我还是想听听:))
显而易见的方法是使用模板专业化.我宁愿不走这条路,因为实际上Foo有很多功能,我不想重复自己.不过,这似乎是我唯一的选择,我可以使用基类实现一些代码共享,如下所示:
// Base functionality
template<bool IsCopyable>
struct FooBase
{
FooBase();
// move ctor and assignment can go here
FooBase(FooBase&&);
FooBase& operator=(FooBase&&);
// some generic conversion ctor and assignment that I happen to need
template<class T> FooBase(T&& t);
template<class T> FooBase& operator=(T&&);
// …
Run Code Online (Sandbox Code Playgroud)