簡體   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