#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
std::function<decltype(::bind)> mockbind = ::bind;
int main()
{
}
上面的代码适用于我编译的大多数平台。但是在使用g ++ - 7的ubuntu 14.04上我收到一个错误:
X.cpp:7:65: error: variable ‘std::function<int(int, const sockaddr*, unsigned int) noexcept> mockbind’ has initializer but incomplete type
std::function<int(int, const sockaddr*, unsigned int) noexcept> mockbind = ::bind;
^~~~~~~~
现在,如果我手动去改变mockbind
std::function<int(int, const sockaddr*, unsigned int) noexcept> mockbind = ::bind;
正如所料,我得到了同样的错误:
现在,如果我删除noexcept
std::function<int(int, const sockaddr*, unsigned int)> mockbind = ::bind;
按预期编译。
所以问题是我可以应用一些模板代码从noexcept
返回的类型中删除decltype
并使其按预期工作。
答案 0 :(得分:12)
一个简单的类专门化技巧应该有效:
template <typename T> struct remove_noexcept
{
using type = T;
};
template <typename R, typename ...P> struct remove_noexcept<R(P...) noexcept>
{
using type = R(P...);
};
template <typename T> using remove_noexcept_t = typename remove_noexcept<T>::type;
// ...
std::function<remove_noexcept_t<decltype(::bind)>> mockbind = ::bind;
您可以在某种程度上轻松扩展它以从[成员]函数指针中删除noexcept
,这将作为阅读器的左侧。
如果您希望在没有using type = T;
的情况下获得编译时错误而不是保持类型不变,则可以注释掉noexcept
。
答案 1 :(得分:0)
虽然HolyBlackCat的答案涵盖了大多数实际用例,但它无法涵盖许多可能的情况,包括qualified function type(例如int(int) const noexcept
),可变参数化可变参数函数(例如{{ 1}})和指向成员函数的指针(这些成员函数完全不在常规的 pointer 规则下运行,例如template<typename... Ts> void foo(Ts..., ...) noexcept
)。
实现涵盖所有这些极端情况的int(foo::*)(int) noexcept
特征并不是一件容易的事,但这是我的责任。我用remove_noexcept
来实现remove_noexcept_t
,它的第二个参数允许您切换结果make_noexcept_t<T, bool>
的状态(如您所愿,noexcept
或noexcept(true)
)
值得注意的是,此可以用于指向成员函数的指针,但不能可以用于函数指针。这是设计使然(主要遵循noexcept(false)
的逻辑),尽管您可以很容易地像std::is_pointer
那样建立using
声明。
Live Demo(更新)
编辑:在发布此内容之前,未使用MSVC ++ 2019(v142)对以下实现进行准确性测试。尽管它可以与GCC和Clang一起使用,但此实现对MSVC ++ 2019(v142)不能起作用。实时演示链接已更新为更长的时间实现(专业化程度的两倍),太长了,无法发布到StackOverflow。该实现已在GCC,Clang和MSVC ++ 2019(v142)中进行了测试。
add_pointer_t<make_noexcept_t<remove_pointer_t<decay_t<T>>>>