[英]explicit constructor still doing conversions
我有一個(非常)簡單的模板化類型,它允許我從函數返回時返回“IsValid”標志。 它如下:
template <typename T>
struct Validated
{
private:
T m_value;
bool m_isValid;
public:
Validated() : m_value(), m_isValid(false) {}
explicit Validated(T const& value) : m_value(value), m_isValid(true) {}
explicit Validated(bool isValid, T const& value) : m_value(value), m_isValid(isValid) {}
explicit Validated(bool isValid, T&& value) : m_value(value), m_isValid(isValid) {}
bool IsValid() const { return m_isValid; }
T const& Value() const { return m_value; }
};
也許有一些我不明白的explicit
說明符,但我想知道為什么以下工作正常,我怎么能避免從bool轉換為double?
void someFunc()
{
Validated<double> foo(1.0); // this makes perfect sense
Validated<double> bar(true); // works... (sets m_value to 1.0)
}
一直在看類似的問題/答案,但找不到任何令人滿意的問題。 我知道std::optional
存在,但我們還沒有進入c ++ 17。 在VS2012 / v110上試過這個。
更新:根據建議,刪除bool的構造函數可以完成工作(從c ++ 14開始)。 它不適用於c ++ 11(VS2012 / toolset v110)。
你可以簡單地刪除一個bool
的構造函數:
Validated(bool value) = delete;
注意:如果您希望Validated<bool>
是有效類型,則可能需要一些額外的預防措施。
您還可以防止除T
之外的任何類型的構造(比前一個更強):
template <class U>
Validated(U) = delete;
這甚至可以使用Validated<bool>
因為T
構造將匹配您的Validated(T const&)
重載,而來自T
以外的任何類型的構造將匹配已刪除的模板。
此方法將防止(甚至明確)建設Validated<double>
從1
, 1f
,等等,所以你可能不希望使用它。
explicit
不會使您的代碼格式錯誤,它會阻止從T
隱式構造Validated<T>
,例如:
void f(Validated<double>);
f(1.0); // ill-formed because the conversion would be implicit
你可以在所有情況下禁用Validated(bool)構造函數,除了T = bool之類的東西...
#include <iostream>
#include <type_traits>
using namespace std;
template <typename T>
struct Validated
{
private:
T m_value;
bool m_isValid;
public:
Validated() : m_value(), m_isValid(false) {}
explicit Validated(T const& value) : m_value(value), m_isValid(true) {}
template <typename Y=T,typename std::enable_if<!std::is_same<Y,bool>::value,int>::type =0>
explicit Validated(bool const& value) = delete;
explicit Validated(bool isValid, T const& value) : m_value(value), m_isValid(isValid) {}
explicit Validated(bool isValid, T&& value) : m_value(value), m_isValid(isValid) {}
bool IsValid() const { return m_isValid; }
T const& Value() const { return m_value; }
};
int main() {
Validated<bool> v(true);
//Validated<int> v2(true); //fails
Validated<int> v2(2);
return 0;
}
這里的問題是傳遞給構造函數的參數可以隱式轉換為構造函數參數類型。 為了防止這種情況,您可以將構造函數轉換為模板,並檢查參數類型是否與模板參數完全匹配:
template<typename TT> explicit
Validated(TT const& value) : m_value{value}, m_isValid{true}
{
static_assert
(
::std::is_same_v<TT, T>
, "constructor argument type should match template parameter"
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.