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

时间:2009-06-04 09:17:42

标签: c++ boost

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

例如:

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

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

7 个答案:

答案 0 :(得分:7)

检查特定函数是否存在的常用方法是获取其地址并将其分配给虚拟变量。这比目前提到的测试要精确得多,因为这会验证确切的函数签名。问题特别是签名中的 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)这样的类似构造函数。

答案 1 :(得分:3)

如果您真的需要它,可以添加此功能:

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

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

此外,如果代码中出现这种情况,您可以将其模板化甚至制作宏。

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

答案 2 :(得分:3)

如果您正在尝试检查foo是否可以从字符串构造,则可以使用boost::is_convertible

例如:

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

答案 3 :(得分:2)

在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);
    }
};

答案 4 :(得分:2)

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

以下是在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)"
);

答案 5 :(得分:0)

你要求的声音很像单元测试。我会下载类似cppunit的内容并将其集成到您的编辑中。

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

答案 6 :(得分:0)

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

我建议您去看一下概念检查库(文档 here )。您可以找到一些可以帮助您的文档,类和宏。