模板通过一个专门化同时接受throw和nothrow
template accept both throw and nothrow with one specialization
我想编写一个同时接受普通签名和非异常签名的模板类MyClass
。例如CCD_ 2和CCD_。
这就是我尝试过的:
template<typename TSignature>
struct IsNoThrow;
template<typename TReturn, typename...TArgs>
struct IsNoThrow<TReturn(TArgs...)> {
static constexpr bool value = false;
};
template<typename TReturn, typename...TArgs>
struct IsNoThrow<TReturn(TArgs...) noexcept> {
static constexpr bool value = true;
};
template<typename T, bool = IsNoThrow<T>::value>
class MyClass;
template<bool BNoThrow, typename TReturn, typename...TParams>
class MyClass<TReturn(TParams...) noexcept(BNoThrow), BNoThrow> {
//VS2017(/std:c++latest) gives error C2057: expected constant expression
};
int main() {
MyClass<int()> mc;
}
为什么我得到错误C2057?如果不像使用IsNoThrow
那样两次专门化MyClass
,我怎么能做到这一点?
为什么我得到错误C2057?我怎么能在不像IsNoThrow那样两次专门化MyClass的情况下做到这一点?
我想这个错误是VC错误,但无论如何,你的解决方案对我来说似乎过于复杂了。
我建议
(1) 从std::true_type
和std::false_type
继承IsNoThrow
(以简化和使用std::integral_constant
中的设施)
template<typename TSignature>
struct IsNoThrow;
template<typename TReturn, typename...TArgs>
struct IsNoThrow<TReturn(TArgs...)> : public std::false_type
{ };
template<typename TReturn, typename...TArgs>
struct IsNoThrow<TReturn(TArgs...) noexcept> : public std::true_type
{ };
或者,也许,简单的
template<typename TSignature>
struct IsNoThrow;
template<typename TReturn, typename...TArgs, bool B>
struct IsNoThrow<TReturn(TArgs...) noexcept(B)> : public std::integral_constant<bool, B>
{ };
(2) 如果你对函数的返回类型和参数类型不感兴趣(但只对拦截函数和检测它们是否抛出),那么只对继承自IsNoThrow
的MyClass
的主类/结构(没有专门化)感兴趣
template<typename T>
struct MyClass : public IsNoThrow<T>
{ };
这种方式MyClass
仅在T
类型是函数类型(MyClass<int>
给出编译错误)并且根据noexcept
值从std::true_type
或从std::false_type
继承时进行编译。
#include <type_traits>
template<typename TSignature>
struct IsNoThrow;
template<typename TReturn, typename...TArgs>
struct IsNoThrow<TReturn(TArgs...)> : public std::false_type
{ };
template<typename TReturn, typename...TArgs>
struct IsNoThrow<TReturn(TArgs...) noexcept> : public std::true_type
{ };
template<typename T>
struct MyClass : public IsNoThrow<T>
{ };
int foo (int)
{ return 0; }
int bar (int) noexcept
{ return 0; }
int main()
{
static_assert( false == MyClass<decltype(foo)>::value );
static_assert( true == MyClass<decltype(bar)>::value );
static_assert( false == MyClass<int(int)>::value );
static_assert( true == MyClass<int(int) noexcept>::value );
//MyClass<int> mc; // compilaton error
}
如果你对返回和参数类型感兴趣,在我看来,你需要一个专业化,一个可能的解决方案是
template<typename T>
struct MyClass;
template<typename TReturn, typename ... TArgs, bool B>
struct MyClass<TReturn(TArgs...) noexcept(B)> : public std::integral_constant<bool, B>
{ };
--编辑--
如果你的VC编译器在推导noexcept(B)
中的布尔值时不支持C++17,我想(假设你还需要推导返回和参数类型)你需要两个MyClass
专门化。
但是,如果你的问题是你必须复制这个专业化的内容,我提出了一个两个专业化的解决方案,其中第二个从第一个继承:
template<typename T, bool = false>
struct MyClass;
template<typename TReturn, typename ... TArgs, bool B>
struct MyClass<TReturn(TArgs...), B> : public std::integral_constant<bool, B>
{ /* all common member/methods here */ };
template<typename TReturn, typename ... TArgs>
struct MyClass<TReturn(TArgs...) noexcept>
: public MyClass<TReturn(TArgs...), true>
{ /* empty: inherhit all from the other specialization */ };
这样,您就不需要MyClass<int()>
0,并且只能开发第一个专业化:其中的所有成员和方法都继承自另一个专业化。
以下是的完整编译示例
#include <type_traits>
template<typename T, bool = false>
struct MyClass;
template<typename TReturn, typename ... TArgs, bool B>
struct MyClass<TReturn(TArgs...), B> : public std::integral_constant<bool, B>
{
/* all common member/methods here */
static constexpr bool isNoExcept ()
{ return B; }
};
template<typename TReturn, typename ... TArgs>
struct MyClass<TReturn(TArgs...) noexcept>
: public MyClass<TReturn(TArgs...), true>
{ /* empty: inherhit all from the other specialization */ };
int foo (int)
{ return 0; }
int bar (int) noexcept
{ return 0; }
int main()
{
// using value
static_assert( false == MyClass<decltype(foo)>::value );
static_assert( true == MyClass<decltype(bar)>::value );
static_assert( false == MyClass<int(int)>::value );
static_assert( true == MyClass<int(int) noexcept>::value );
// using isNoExcept()
static_assert( false == MyClass<decltype(foo)>::isNoExcept() );
static_assert( true == MyClass<decltype(bar)>::isNoExcept() );
static_assert( false == MyClass<int(int)>::isNoExcept() );
static_assert( true == MyClass<int(int) noexcept>::isNoExcept() );
//MyClass<int> mc; // compilaton error
}
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- `throw 1` in C++
- gnuradio c++ connect self() throw bad_weak_ptr
- new(std::nothrow) int[n] 抛出异常
- 为什么 c++ 使用 throw() 关键字来指示函数不会引发任何异常
- 是否有任何版本的C++(甚至是试行标准)是"throw()"并不意味着"cannot throw, ever"?
- 使用未声明的标识符"nothrow";你是说"扔"吗?记忆
- std::make_shared 和 std::make_unique 有"nothrow"版本吗?
- 实现此"on error, throw"回调的最佳方法是什么?
- 是否有理由大多数/所有 try-catch 示例只对 throw 语句使用 void 子函数
- throw() 函数应该总是在异常时展开堆栈并允许捕获异常还是必须调用 std::terminate ?
- GCC/GCOV 为 使用 throw() / noexexcept 函数生成的不同分支覆盖
- Poco::Net::HTTPClientSession throw exception without unique_
- 防止在将未引发的异常作为参数传递时在"throw e;"中切片
- Linux g++ new (std::nothrow) 确实有效
- 模板通过一个专门化同时接受throw和nothrow
- 处理"Thrown exception type is not nothrow copy constructible"警告
- 是否可以从输入流中'throw away'读取值?
- 将函数声明为 __attribute__(nothrow) 和 'throw()' 有什么区别
- throw()(即__declspec(nothrow))在视觉C++中是否带来了真正的好处