![](/img/trans.png)
[英]C++ how to check the signature of a template parameter class at compile time
[英]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);
}
};
如果您需要這種檢查,您可能需要一些其他編譯時間檢查
我建議看看增強概念檢查庫(文檔在這里 )。 您可以找到一些可以幫助您的文檔,類和宏。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.