Mic*_*ros 4 c++ boost boost-proto
在测试聚合类型时,我尝试使用boost :: proto :: is_aggregate来检查我正在创建的类型是否真正聚合.我写了这段代码:
#include <iostream>
#include <boost\proto\traits.hpp>
struct IsAggregate
{
IsAggregate &operator=(IsAggregate const &rhs) {}
};
int main()
{
std::cout << std::boolalpha;
std::cout << boost::proto::is_aggregate<IsAggregate>() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我期望输出为真,因为聚合类型可以定义一个拷贝赋值运算符(根据这个:什么是聚合和POD以及它们如何/为什么特殊?)
但输出是错误的.
我还使用了上一个答案中的聚合类,它应该返回true但返回false.
这是使用英特尔编译器和MSVC在Boost 1.5.9上测试的.
有关为何发生这种情况的任何想法?
Proto的特性显然不是为了更广泛的使用.
它默认只调用POD聚合,然后简单地将3 - 库内部类型列为聚合.文档中描述的行为表明它是在那里划伤一个痒(这些make<>函数需要一种方法来了解哪些类型与哪些类型T{}一起使用T()).
退后一步,你应该首先重新考虑你想要这个特性的原因.您最有可能使您的概念检查更具体.
向标准库添加特征的提议已得到广泛支持的拒绝:
我对这个特性有所保留.我们在添加无用的特征如is_pod和is_literal_type时犯了一个错误,我们不应该通过添加更多无用的特征来弥补这个错误.
在我看来,类型traits应该捕获类型的可观察属性(例如,"我可以从braced-init-list直接初始化这个类型吗?"),而不是核心语言ephemera(例如"这种类型服从文字吗?"类型规则,这是一个需要编译器诊断的拐杖?"或"将支持此类型的初始化执行聚合初始化,还是会调用构造函数?").
此外,我认为类型应该能够在聚合和提供等效构造函数集之间切换,而不必担心某人可能正在观察差异.
我已经查看了要求,并得出结论很难/不可能做出一个简单的实现.我无法以编程方式解决的第一个要求是
没有基类(第10条)
没有办法告诉一个类没有(公共,空等)基类.
所以我能提出的最好的事情只是近似:
template <typename T>
struct is_aggregate : std::integral_constant<bool,
std::is_pod<T>() or
(
std::is_trivially_constructible<T>()
and std::is_trivially_destructible<T>()
and std::is_standard_layout<T>()
and not std::is_polymorphic<T>()
)
>
{ };
Run Code Online (Sandbox Code Playgroud)
考虑到这些限制,它似乎做得相当好,至少/比Proto的内部特性好很多/更好.
CAVEAT 这并没有解决c ++ 11/c ++ 14中的细微变化(例如与类内成员初始化程序相关).用于组成上述近似的一些特征在各种编译器版本(特别是MSVC,我记得)上已知问题,因此不要相信这个特性在所有语言/库版本中都是准确的.
#include <iostream>
#include <type_traits>
#include <string>
template <typename T>
struct is_aggregate : std::integral_constant<bool,
std::is_pod<T>() or
(
std::is_trivially_constructible<T>()
and std::is_trivially_destructible<T>()
and std::is_standard_layout<T>()
and not std::is_polymorphic<T>()
)
>
{ };
namespace simple { // ok
struct X {
int x;
X &operator=(X const &/*rhs*/) { return *this; }
};
static_assert(is_aggregate<X>(), "");
void foo() { X x { 42 }; (void) x; }
}
namespace usr_defined_ctor { // NOT ok
struct X {
int x;
X &operator=(X const &/*rhs*/) { return *this; }
X() {}
};
static_assert(!is_aggregate<X>(), "");
//void foo() { X x { 42 }; (void) x; }
}
namespace defaulted_ctor { // ok
struct X {
int x;
X &operator=(X const &/*rhs*/) { return *this; }
X() = default;
};
static_assert( is_aggregate<X>(), "");
void foo() { X x { 42 }; (void) x; }
}
namespace static_data_members { // ok
struct X {
int x;
X &operator=(X const &/*rhs*/) { return *this; }
X() = default;
static const bool yeah = true;
private:
static const bool no = true;
protected:
static const std::string problem;
};
bool const X::yeah;
bool const X::no;
std::string const X::problem = "whatsoever";
static_assert( is_aggregate<X>(), "");
void foo() { X x { 42 }; (void) x; }
}
namespace private_non_static_data_members { // NOT ok
struct X {
int x;
X &operator=(X const &/*rhs*/) { (void) oops; return *this; }
private:
bool oops;
};
static_assert(!is_aggregate<X>(), "");
//void foo() { X x { 42, true }; (void) x; }
}
namespace protected_non_static_data_members { // NOT ok
struct X {
int x;
X &operator=(X const &/*rhs*/) { return *this; }
protected:
bool oops;
};
static_assert(!is_aggregate<X>(), "");
//void foo() { X x { 42, true }; (void) x; };
}
namespace have_base_class { // NOT ok
struct B {};
struct X : B {
int x;
X &operator=(X const &/*rhs*/) { return *this; }
};
static_assert(is_aggregate<X>(), ""); // FALSE POSITIVE: the below fails to compile
//void foo() { X x { 42 }; (void) x; };
}
int main() { }
Run Code Online (Sandbox Code Playgroud)
Coliru干净地编译(没有静态断言):
g++ -std=c++0x -O2 -Wall -pedantic -pthread main.cpp
g++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp
g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp
g++ -std=c++1y -O2 -Wall -pedantic -pthread main.cpp
g++ -std=c++1z -O2 -Wall -pedantic -pthread main.cpp
clang++ -std=c++0x -O2 -Wall -pedantic -pthread main.cpp
clang++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp
clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp
clang++ -std=c++1y -O2 -Wall -pedantic -pthread main.cpp
clang++ -std=c++1z -O2 -Wall -pedantic -pthread main.cpp
clang++ -stdlib=libc++ -std=c++0x -O2 -Wall -pedantic -pthread main.cpp
clang++ -stdlib=libc++ -std=c++11 -O2 -Wall -pedantic -pthread main.cpp
clang++ -stdlib=libc++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp
clang++ -stdlib=libc++ -std=c++1y -O2 -Wall -pedantic -pthread main.cpp
clang++ -stdlib=libc++ -std=c++1z -O2 -Wall -pedantic -pthread main.cpp
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
153 次 |
| 最近记录: |