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
 }