我需要检查一个类C是否有一个默认的构造函数,无论是隐式的还是自定义的,或者是public,protected或者private.
我尝试使用std::is_default_constructible<C>::value,如果返回真C有一个public默认的构造函数(隐式或自定义),但false如果C有一个protected或private默认的构造函数(接缝是标准的行为虽然).
有没有办法检查一个类是否有一个protected或private默认的构造函数?
注意(如果这可能有帮助):检查是从要检查friend的类的函数执行的C.
我需要执行此检查,以便默认构造对应于元组nullptr指针的对象,对象的m_objs成员Foo(下面的部分Foo定义):
template<class... Objects>
class Foo
{
public:
Foo(Objects*... objects)
: m_objs(objects...)
{
// User construct a Foo objects passing a pack of pointers
// some of them are nullptr, some are not.
// The following call should default-construct objects corresponding
// to the null pointers of m_objs member tuple:
objs_ctor<Objects...>();
}
private:
template<class Obj, class O1, class ...On>
void objs_ctor()
{
objs_ctor<Obj>(); objs_ctor<O1, On...>();
}
template<class Obj>
typename std::enable_if<std::is_default_constructible<Obj>::value, void>::type
objs_ctor()
{
Obj*& obj = std::get<Obj*>(m_objs);
if (obj == nullptr)
obj = new Obj; // default-construct Obj
}
template<class Obj>
typename std::enable_if<!std::is_default_constructible<Obj>::value, void>::type
objs_ctor()
{
Obj*& obj = std::get<Obj*>(m_objs);
assert(obj != nullptr); // terminate if not pre-constructed
}
private:
std::tuple<Objects*...> m_objs;
};
Run Code Online (Sandbox Code Playgroud)
它旨在用作:
struct A { };
class B {
B() = default;
template <class... Ts>
friend class Foo;
};
int main() {
// currently asserts, even though Foo<A,B> is a friend of B
// and B is default-constructible to its friends
Foo<A, B> foo(nullptr, nullptr);
}
Run Code Online (Sandbox Code Playgroud)
上面的例子断言因为std::is_default_constructible<B>::value是假的,即使B有[私人]默认ctor并且Foo<A,B>是B的朋友.
我将展示一个简化的例子,让事情变得更容易。然后你可以将它调整到你的 Foos 类。这个想法是专门化我的模板化朋友类如下
#include <iostream>
// forward declaration
template <class... T>
struct Friend;
struct testing_tag;
// specialisation simply to check if default constructible
template <class T>
struct Friend<T, testing_tag> {
// sfinae trick has to be nested in the Friend class
// this candidate will be ignored if X does not have a default constructor
template <class X, class = decltype(X())>
static std::true_type test(X*);
template <class X>
static std::false_type test(...);
static constexpr bool value = decltype(test<T>(0))::value;
};
Run Code Online (Sandbox Code Playgroud)
请注意,只要 X 具有默认构造函数,无论它是私有的、受保护的还是公共的,std::true_type 候选对象将始终有效。现在测试一下
class default_public {
template <class... T>
friend struct Friend;
};
class default_protected {
template <class... T>
friend struct Friend;
protected:
default_protected() {}
};
class default_private {
template <class... T>
friend struct Friend;
private:
default_private() {}
};
class no_default {
public:
no_default(int x){}
};
// a convenient name to test with
template <class T>
using has_any_default_constructor = Friend<T, testing_tag>;
int main() {
std::cout << has_any_default_constructor<default_public>::value << std::endl;
std::cout << has_any_default_constructor<default_protected>::value << std::endl;
std::cout << has_any_default_constructor<default_private>::value << std::endl;
std::cout << has_any_default_constructor<no_default>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2016 次 |
| 最近记录: |