Почему я получил эту ошибку C2057? Как я могу сделать это, не специализируя MyClass дважды, как я это делал с IsNoThrow?
Полагаю, ошибка связана с ошибкой VC, но в любом случае ваше решение мне кажется слишком сложным.
Я предлагаю
(1) наследование, для IsNoThrow
, от std::true_type
и std::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
является типом функции (MyClass<int>
дает ошибку компиляции) и наследуется от std::true_type
или от std::false_type
согласно noexcept
значению.
#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 не поддерживает C ++ 17 в момент вывода логического значения в noexcept(B)
, я полагаю, что (учитывая, что вам нужно также вывести типы возврата и аргументы), вам нужно две специализации 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
}