小编Red*_*Fog的帖子

为什么我们不能在内联命名空间之外声明演绎指南?

例子:

namespace X{
    inline namespace Y{
        template<typename T>
        struct A{
        };
    }
}
namespace X{
    template<typename Z>
    A(std::vector<Z>) -> A<Z>;
}
Run Code Online (Sandbox Code Playgroud)

这会在 Clang 11 中导致编译错误,它说“演绎指南必须在与模板相同的范围内声明X::Y::A

与模板特化类似,推导指南也应在与类模板相同的语义范围内声明。那么为什么我可以在内联命名空间之外专门化类模板,但对于推导指南我不能?

特别是,这会导致另一个问题:

template<typename T>
struct Q{
    operator std::vector<T>() {
        return {};
    }
};

namespace std{
    template<typename T>
    vector(Q<T>) -> vector<T>;
}
Run Code Online (Sandbox Code Playgroud)

如果我想定义一个转换为 的类模板并为其std::vector声明一个推导指南,编译器会拒绝 。在这种情况下(对于 libc++),我必须在namespace std::__1.

CPP标准中是否有一些解决方案或解释?

c++ templates c++17 ctad

5
推荐指数
1
解决办法
292
查看次数

多次调用 std::forward&lt;Func&gt; 的正确方法是什么?

示例:(它不假设func是纯的、可复制构造的或可移动构造的)

template<typename Func>
void dispatch(std::vector<int>& cont, Func&& func){
    for (auto& v : cont)
        std::forward<Func>(func)(v);
}
Run Code Online (Sandbox Code Playgroud)

在标准实践中,我们应该通过 接收一个函数对象,Func&&然后通过 调用它std::forward<Func>(func)(args...),以避免任何复制或移动,并选择 的正确重载operator()。但有一个问题:如果是一个右值并且它本身移动会发生什么?funcoperator() &&

显然,一个可能的结果是,有效但不确定的 func被调用,我认为这是一种未指定的行为。

那么如何避免这个问题呢?我认为复制构造性和纯度不是可接受的成本。operator() &调用n - 1 次和一次怎么样operator() &&

编辑:

在这个问题中,它不依赖于任何实际问题。这只是一个思想实验,旨在找到一种更通用的方法来处理这种情况。

在评论中,我得到了一些解决方案:

  1. 路过副本。但Func不一定是可复制构造或可移动构造的。即使是,解决方案也等于 call operator() &,为什么不func()直接使用呢?

  2. 总是打电话operator() &。这好像是:

template<typename Func>
void dispatch(std::vector<int>& cont, Func&& func){
    for (auto& v : cont)
        func(v);
}
Run Code Online (Sandbox Code Playgroud)

这是解决这个问题的好方法,而且总是不会给用户带来任何惊喜。但我认为它失去了 的右值属性func …

c++ templates language-lawyer perfect-forwarding c++11

5
推荐指数
0
解决办法
365
查看次数

为什么返回类型推导不能支持带有 std::is_invocable_v 的 SFINAE

有一些函子具有返回类型推导,包括lambda 表达式

constexpr auto a = [](auto&& x){ return x + 1; };
struct X{
    template<typename T>
    auto operator()(T&& x){
        return x + 1;
    }
};
Run Code Online (Sandbox Code Playgroud)

然后,我有 2 个函数来检查参数是否可以应用于这些函子,即SFINAEstd::is_invocable_vSFINAE

template<typename F, typename T, std::enable_if_t<std::is_invocable_v<F, T>, int> = 0>
void foo(T a){
    std::cout << "yes" << std::endl;
}
template<typename F, typename T, std::enable_if_t<!std::is_invocable_v<F, T>, int> = 0>
void foo(T a){
    std::cout << "no" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

最后,我使用foo<X>(0)or foo<decltype(a)>(0),它运行良好并显示“是”,因为检查已通过。但是当我使用foo<X>((void*)0)or时 …

c++ sfinae language-lawyer return-type-deduction c++17

1
推荐指数
1
解决办法
338
查看次数