繁体   English   中英

检查编译时的类构造函数签名

[英]Check at compile time class constructor signature

有没有办法在编译时检查某些类是否具有某些参数的构造函数?

例如:

class foo {
    foo(std::string &s) {
    }
};

我想在编译时检查构造函数与std :: string并始终定义。 也许boost提供了这样的功能?

检查特定函数是否存在的常用方法是获取其地址并将其分配给虚拟变量。 这比目前提到的测试要精确得多,因为这会验证确切的函数签名。 问题是关于string&在签名中,所以非const,因此可能修改字符串。

但是,在这种情况下,您不能使用take-the-address-and-assign-it技巧:构造函数没有地址。 那么,你如何检查签名呢? 简单地说:在虚拟课堂上与它交朋友。

template<typename T>
class checkSignature_StringRef {
    friend T::T(string&);
};

这也是一个非常具体的检查:它甚至不会匹配类似的构造函数,如foo::foo(std::string &s, int dummy = 0)

我想出了一个类似的问题,希望在参数兼容时将构造函数转发给基类,并在没有时执行其他操作。

这是在MSVC 2013上工作的一般化特征(需要C ++ 11的东西):

namespace detail {
    template<class type,class...Args>
    class constructible_from
    {
        template<class C>
        static C arg();

        template <typename U>
        static boost::mpl::true_ constructible_test(U *, decltype( U(arg<Args>()...) ) * = 0 );
        static boost::mpl::false_ constructible_test(...);

    public:

        typedef decltype( constructible_test(static_cast<type*>(nullptr)) ) result;

    };
}   // namespace detail

template<class type>
struct constructible
{
    template<class...Args>
    struct from :
        detail::constructible_from<type,Args...>::result {};
};

这是一个特征用法示例,我将enable_if应用程序作为练习:D:

struct b{};
struct c{};
struct d : c{};

struct a
{
    a() {}
    a(a &) {}
    a(b,c) {}
    a(c) {}
};


static_assert(
    constructible<a>::from<>::value,
    "a()"
);
static_assert(
    constructible<a>::from<a&>::value,
    "a(a&)"
);
static_assert(
    ! constructible<a>::from<const a&>::value,
    "a(const a&)"
);
static_assert(
    constructible<a>::from<b,c>::value,
    "a(b,c)"
);
static_assert(
    ! constructible<a>::from<b>::value,
    "a(b)"
);
static_assert(
    constructible<a>::from<c>::value,
    "a(c)"
);
static_assert(
    constructible<a>::from<d>::value,
    "a(d)"
);

如果你真的需要它,你可以添加这个功能:

static void _dummy() { std::string s; foo f(s); }

如果没有构造函数,编译将失败。 注意:您的构造函数是私有的。 如果它是故意的,那么_dummy应该在课堂内。 否则,您可以在课外进行。

此外,如果代码中发生了很多这种情况,您可以模板化甚至将其设为宏。

但说实话,它仍然看起来像一个黑客。 你确定需要它吗?

如果你试图检查foo是否可以从字符串构造,你可以使用boost::is_convertible

例如:

BOOST_STATIC_ASSERT((boost::is_convertible<std::string, foo>::value));

在boost 1.39中使用Concept检查:

#include <boost/concept_check.hpp>

class foo_c
{
public:
    foo_c(std::string& s)
    {}
};

template<typename T>
class algo_c
{
BOOST_CONCEPT_ASSERT((boost::Convertible<std::string,T>));
public:
    algo_c()
    {}
};

删除或更改foo_c的构造函数会导致以下编译时错误:

错误C2440:'初始化':无法从'std :: string'转换为'foo_c'

编辑:这可以使用显式构造函数与自制概念检查:

template <typename T>
struct HasTheRightConstructor
{
    BOOST_CONCEPT_USAGE(HasTheRightConstructor)
    {
        std::string v;
        T j(v);
    }
};

您要求的声音听起来很像单元测试。 我会下载类似cppunit的东西并将其集成到您的编译中。

您编写的任何单元测试都将在编译时构建/执行。 有关更多信息,请参阅单元测试

如果您需要这种检查,您可能需要一些其他编译时间检查

我建议看看增强概念检查库(文档在这里 )。 您可以找到一些可以帮助您的文档,类和宏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM