C++ 模板接受带有一个专门化的throw和nothrow
我想编写一个模板类C++ 模板接受带有一个专门化的throw和nothrow,c++,templates,c++17,variadic-templates,template-meta-programming,C++,Templates,C++17,Variadic Templates,Template Meta Programming,我想编写一个模板类MyClass,它同时接受普通和无异常签名。例如MyClass和MyClass 这就是我尝试过的: template<typename TSignature> struct IsNoThrow; template<typename TReturn, typename...TArgs> struct IsNoThrow<TReturn(TArgs...)> { static constexpr bool value = false;
MyClass
,它同时接受普通和无异常签名。例如MyClass
和MyClass
这就是我尝试过的:
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;
}
模板
struct不是row;
模板
struct IsNoThrow{
静态constexpr bool值=false;
};
模板
struct IsNoThrow{
静态constexpr布尔值=真;
};
模板
类MyClass;
模板
类MyClass{
//VS2017(/std:c++最新版本)给出错误C2057:预期的常量表达式
};
int main(){
MyClass mc;
}
为什么我会犯这个错误?如果我没有像对待IsNoThrow一样专门化两次MyClass
,我怎么能做到这一点呢
为什么我会犯这个错误?我怎么能像对待IsNoThrow那样,不把我的课程专门化两次呢
我想这是一个VC错误,但无论如何,你的解决方案对我来说太复杂了
我提议
(1) 继承,对于IsNoThrow
,来自std::true\u type
和std::false\u type
(简化并使用std::integral\u常量中的工具)
这种方式MyClass
仅当T
类型是函数类型(MyClass
给出编译错误)并且根据noexcept
值从std::true\u type
或从std::false\u 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
}
这样,您就不需要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
}
#包括
模板
结构MyClass;
模板
struct MyClass:public std::integral\u常量
{
/*所有常用的成员/方法都在这里*/
静态constexpr bool isNoExcept()
{返回B;}
};
模板
结构MyClass
:公共MyClass
{/*empty:inherhit all from the other specialization*/};
int foo(int)
{返回0;}
整型条(整型)无例外
{返回0;}
int main()
{
//使用价值
静态断言(false==MyClass::value);
静态断言(true==MyClass::value);
静态断言(false==MyClass::value);
静态断言(true==MyClass::value);
//使用isNoExcept()
静态_断言(false==MyClass::isNoExcept());
静态_断言(true==MyClass::isNoExcept());
静态_断言(false==MyClass::isNoExcept());
静态_断言(true==MyClass::isNoExcept());
//MyClass mc;//编译错误
}
MSVC还不完全支持C++17。我认为您没有任何追索权。不幸的是,MyClass需要知道返回类型和所有参数types@JohnSmith-所以你需要专业化。。。给我几分钟。@JohnSmith-答案有所改进。我得到了一个错误C2764:“B”:模板参数未在部分专门化MyClass中使用或可推断。错误中甚至没有异常(B)
。也许我应该等到VS.@JohnSmith-answer-improved中完全支持c++17(添加了另一个示例),以防您的问题是两个专门化中的代码重复。
template<typename T>
struct MyClass : public IsNoThrow<T>
{ };
#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>
{ };
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 */ };
#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
}