C++11 静态断言类继承以终止编译(通过SFINAE?) 目标
假设C++11 静态断言类继承以终止编译(通过SFINAE?) 目标,c++11,sfinae,static-assert,C++11,Sfinae,Static Assert,假设模板类神话有大量使用语句,例如使用T::my_def或使用T::my_other_def。由于明显的原因,如果T没有定义my_def和my_other_def,编译将失败然而,实际用例中的编译失败会导致数百个错误,使用户难以理解实际问题。虽然编译失败是“足够好”,但我真的很想通过某种聪明的代理类找到一种提前终止编译的方法。首先,为了完整性,包括SFINAE设置。第二个是如何使用函数实现这一点的推论示例。然后是我的尝试,以及怀疑为什么这实际上不可能的原因(但我希望是错误的) 注意:这是一个“严
模板类神话
有大量使用
语句,例如使用T::my_def
或使用T::my_other_def
。由于明显的原因,如果T
没有定义my_def
和my_other_def
,编译将失败然而,实际用例中的编译失败会导致数百个错误,使用户难以理解实际问题。虽然编译失败是“足够好”,但我真的很想通过某种聪明的代理类找到一种提前终止编译的方法。首先,为了完整性,包括SFINAE设置。第二个是如何使用函数实现这一点的推论示例。然后是我的尝试,以及怀疑为什么这实际上不可能的原因(但我希望是错误的)
注意:这是一个“严格”的C++11项目(但我不反对导入类型,例如,std::void\t
已经成功了,尽管我在std::conditional
失败)。如果您知道这些内容,请跳到第2节,并注意:
是一个is_valid()
函数,其行为类似于静态constexpr bool
,检查std::conditional
和my_def
是否为my_other_def
中的有效类型名T
///////////////////////////////////////////////////////
//测试
结构良好{
使用my_def=float;
使用my_other_def=int;
};
使用my_def=double;}构造几乎_1{;
结构几乎2{使用my_other_def=bool;};
结构错误{};
int main(int argc,常量字符**argv){
//健康检查
std::cout希望有另一种方法,但似乎最简单的解决方案是另一种方法:用户应该实例化的类没有实际的实现,而内部
类就完成了这一切
namespace internal {
template <class T, bool valid>
struct TheClass {
static_assert(valid, "Template 'class T' must have static types `my_def` and `my_other_def`.");
};
template <class T>
struct TheClass<T, true> {
// compiler warning 2
using my_def = typename T::my_def;
// compiler warning 3
using my_other_def = typename T::my_other_def;
std::string message() {
return "work gets done";
}
};
}
template <class T>
struct TheClass : internal::TheClass<T, is_valid<T>()> { };
struct Good {
using my_def = float;
using my_other_def = int;
};
struct Almost_1 { using my_def = double; };
int main(int argc, const char **argv) {
TheClass<Good> g;
std::cout << "Good message: " << g.message() << std::endl;
// only one static assert
TheClass<Almost_1> a1;
return 0;
}
名称空间内部{
模板
结构类{
static_assert(有效,“模板'class T'必须具有静态类型'my_def'和'my_other_def');
};
模板
结构类{
//编译器警告2
使用my_def=typename T::my_def;
//编译器警告3
使用my_other_def=typename T::my_other_def;
std::string消息(){
返回“完成工作”;
}
};
}
模板
结构类:内部::类{};
结构良好{
使用my_def=float;
使用my_other_def=int;
};
使用my_def=double;}构造几乎_1{;
int main(int argc,常量字符**argv){
g类;
std::cout希望有另一种方法,但似乎最简单的解决方案是另一种方法:用户应该实例化的类没有实际的实现,而内部
类就完成了这一切
namespace internal {
template <class T, bool valid>
struct TheClass {
static_assert(valid, "Template 'class T' must have static types `my_def` and `my_other_def`.");
};
template <class T>
struct TheClass<T, true> {
// compiler warning 2
using my_def = typename T::my_def;
// compiler warning 3
using my_other_def = typename T::my_other_def;
std::string message() {
return "work gets done";
}
};
}
template <class T>
struct TheClass : internal::TheClass<T, is_valid<T>()> { };
struct Good {
using my_def = float;
using my_other_def = int;
};
struct Almost_1 { using my_def = double; };
int main(int argc, const char **argv) {
TheClass<Good> g;
std::cout << "Good message: " << g.message() << std::endl;
// only one static assert
TheClass<Almost_1> a1;
return 0;
}
名称空间内部{
模板
结构类{
static_assert(有效,“模板'class T'必须具有静态类型'my_def'和'my_other_def');
};
模板
结构类{
//编译器警告2
使用my_def=typename T::my_def;
//编译器警告3
使用my_other_def=typename T::my_other_def;
std::string消息(){
返回“完成工作”;
}
};
}
模板
结构类:内部::类{};
结构良好{
使用my_def=float;
使用my_other_def=int;
};
使用my_def=double;}构造几乎_1{;
int main(int argc,常量字符**argv){
g类;
std::我可能处于愚蠢的模式,但我找不到你在哪里陈述了你真正想要做的事情…不,是我!我像赫克一样试图使问题尽可能简短,这样做有效地消除了实际问题。通过与函数版本n起作用。我可能处于愚蠢的模式,但我找不到你在哪里陈述了你真正想要做的事情…不,是我!我像赫克一样试图使问题尽可能简短,这样做有效地消除了实际问题。通过与函数版本进行比较,最后的问题引导和概要现在应该让事情更清楚了作品
///////////////////////////////////////////////////////
// Need some more proxying?
namespace internal {
template <class T, bool valid>
struct TheClass {
// compiler warning 1 (seek termination here)
static_assert(valid, "You have been asserted.");
};
template <class T>
struct TheClass<T, true> {
std::string message() { return "You are valid."; }
};
}
template <class T>
struct TheClass : public internal::TheClass<T, is_valid<T>()> {
// compiler warning 2
using my_def = typename T::my_def;
// compiler warning 3
using my_other_def = typename T::my_other_def;
std::string message() {
return internal::TheClass<T, is_valid<T>()>::message();
}
};
///////////////////////////////////////////////////////
// The tests
struct Good {
using my_def = float;
using my_other_def = int;
};
struct Almost_1 { using my_def = double; };
struct Almost_2 { using my_other_def = bool; };
struct Bad {};
int main(int argc, const char **argv) {
// sanity checks
std::cout << std::boolalpha
<< "Good: " << is_valid<Good>() << std::endl
<< "Almost_1: " << is_valid<Almost_1>() << std::endl
<< "Almost_2: " << is_valid<Almost_2>() << std::endl
<< "Bad: " << is_valid<Bad>() << std::endl;
// in function land, uncomment these and it will
// only produce the single static_assert for valid<T>
// rather than continuing on for breaking T
// validate_wrapper<Good>();
// validate_wrapper<Almost_1>();
// At least this works.
TheClass<Good> g;
std::cout << "Good message: " << g.message() << std::endl;
// I would like to achieve just one error from static_assert
// comment out to see that `validate_wrapper<Almost_1>` will
// terminate early (as desired)
TheClass<Almost_1> a1;
return 0;
}
namespace internal {
template <class T, bool valid>
struct TheClass {
static_assert(valid, "Template 'class T' must have static types `my_def` and `my_other_def`.");
};
template <class T>
struct TheClass<T, true> {
// compiler warning 2
using my_def = typename T::my_def;
// compiler warning 3
using my_other_def = typename T::my_other_def;
std::string message() {
return "work gets done";
}
};
}
template <class T>
struct TheClass : internal::TheClass<T, is_valid<T>()> { };
struct Good {
using my_def = float;
using my_other_def = int;
};
struct Almost_1 { using my_def = double; };
int main(int argc, const char **argv) {
TheClass<Good> g;
std::cout << "Good message: " << g.message() << std::endl;
// only one static assert
TheClass<Almost_1> a1;
return 0;
}