gpt4 book ai didi

c++ - 模板接受具有一种特化的 throw 和 nothrow

转载 作者:行者123 更新时间:2023-11-30 04:52:44 25 4
gpt4 key购买 nike

我想写一个模板类MyClass接受 normal 和 noexcept 签名。例如MyClass<int()>MyClass<int() noexcept> .

这是我试过的:

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?不专精怎么办MyClass像我用 IsNoThrow 做的那样两次?

最佳答案

Why I got that error C2057? How can I do it without specializing MyClass twice like I did with IsNoThrow?

我想这个错误是一个 VC 错误,但无论如何,你的解决方案对我来说似乎过于复杂。

我提议

(1)继承,为IsNoThrow , 来自 std::true_typestd::false_type (以简化和使用 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) 如果您对函数的返回类型和参数类型不感兴趣(但只对拦截函数并检测它们是否抛出或不抛出)只有一个主类/结构 MyClass (无特化)继承自 IsNoThrow

template<typename T>
struct MyClass : public IsNoThrow<T>
{ };

这边MyClass仅在 T 时编译type 是函数类型( MyClass<int> 给出编译错误)并继承自 std::true_type或来自 std::false_type根据noexcept值(value)。

#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) 中的 bool 值时不支持 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 */ };

这样你就不需要IsNoThrow并且您只能开发第一个特化:其中的所有成员和方法都继承自另一个特化。

下面是一个完整的编译示例

#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
}

关于c++ - 模板接受具有一种特化的 throw 和 nothrow,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54168109/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com