构造函数解析顺序问题

发布于 2024-11-29 22:48:31 字数 834 浏览 1 评论 0原文

考虑 T 的以下构造函数:

struct T {
    T(const bool) { std::cout << "T(const bool)" << endl; }
    T(const std::string&) { std::cout << "T(const std::string&)" << endl; }
};

T t("");
  1. 为什么在构造 t 时 T(const bool) 优先于 T(const std::string&)
  2. 由于上述优先顺序可能会给希望调用 T(const std::string&) 的用户造成混乱,我该怎么做才能让 T(const std::string&) ) 在将字符串文字传递给 T 的构造函数时隐式调用。目前我发现的唯一解决方法是添加另一个构造函数,该构造函数具有最高优先级:

    T(const char* s)
    {
        std::cout << “T(const char*)”<<结束;
        *这= std::string(s);
    }
    
  3. 除上述之外解决方案,声明显式 T(const bool) 以避免混淆并不能解决上述问题:在这种情况下,虽然现在禁止使用 T t = "",但为什么形式是 T t("") 仍然允许并调用 T(const bool) 吗?

Consider the following constructors for T:

struct T {
    T(const bool) { std::cout << "T(const bool)" << endl; }
    T(const std::string&) { std::cout << "T(const std::string&)" << endl; }
};

T t("");
  1. Why does T(const bool) take precedence over T(const std::string&) when constructing t?
  2. Since the above precedence might cause confusion to users expecting T(const std::string&) to be called, what can I do to have T(const std::string&) implicitly called when passing string literals to the constructor of T. For now the only work around I have found is to add another constructor, which takes the highest precedence:

    T(const char* s)
    {
        std::cout << "T(const char*)" << endl;
        *this = std::string(s);
    }
    
  3. Apart from the above solution, declaring explicit T(const bool) to avoid confusion does not solve the above problem: in this case, although T t = "" is now prohibited, why is the form T t("") is still allowed and does call T(const bool) ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

笨死的猪 2024-12-06 22:48:31

为什么在构造tT(const bool)优先于T(const std::string&)

"" 的类型为 char[1];这可以通过数组到指针的转换隐式转换为 char const*。指针可以隐式转换为 bool,所有非空指针都变为 true,所有空指针都变为 false。这些都是“内置”标准转换。

char const* ->; std::string 转换是用户声明的转换:它利用带有 char const*std::string 转换构造函数。

在重载解析期间,标准(“内置”)转换优于用户声明的转换,因此采用 bool 的构造函数在这里比采用 std::string< 的构造函数更匹配/代码>。

目前我发现的唯一解决方法是添加另一个构造函数

这听起来像是一个合理的解决方案;对于您所描述的简单场景来说,这当然是最直接的解决方案。不过,您对 *this 的赋值有点笨拙;最好让两个构造函数都委托给某个初始化函数。

或者,您可以将带有 enable_if 的模板用于您想要禁止转换的任何构造函数:

template <typename U>
T(U, std::enable_if<std::is_same<U, bool>::value>::type* = 0) { }

此构造函数只能使用 bool 参数进行调用,而不能使用其他参数。您可以在 Boost、C++ TR1 或 C++0x 中找到 enable_ifis_same。您还可以使用 !is_pointeris_integral 或其他一些类型特征组合来允许使用某些其他参数类型,但不允许使用 char const*

或者,作为另一种选择,您可以完全避开 bool 并使用您自己的枚举,以及与构造函数的 truefalse 对应的枚举器。这是否有意义取决于您的用例。

声明显式 T(const bool) 来避免并不能解决上述问题...为什么形式 T t("") 仍然被允许并且确实call T(const bool)?

explicit 仅不允许隐式转换为 TT t(""); 根本没有到 T 的转换;它通过将参数""传递给最匹配的构造函数来构造对象t,从而直接初始化对象t

Why does T(const bool) take precedence over T(const std::string&) when constructing t?

"" is of type char[1]; this is implicitly convertible to char const* via the array-to-pointer conversion. A pointer is implicitly convertible to bool, with all non-null pointers becoming true and all null pointers becoming false. These are both "built-in" standard conversions.

The char const* -> std::string conversion is a user-declared conversion: it utilizes a converting constructor of std::string that takes a char const*.

The standard ("built-in") conversions are preferred over user-declared conversions during overload resolution, so the constructor taking bool is a better match here than the one taking std::string.

For now the only work around I have found is to add another constructor

That sounds like a reasonable solution; certainly the most straightforward solution for the simple scenario you describe. Your use of assignment to *this is a bit clumsy, though; it would be better either to have both constructors delegate to some initialization function.

Alternatively, you could use a template with enable_if for any constructors for which you would like to disallow conversions:

template <typename U>
T(U, std::enable_if<std::is_same<U, bool>::value>::type* = 0) { }

This constructor will only be callable with a bool argument and nothing else. You can find enable_if and is_same in Boost, C++ TR1, or C++0x. You could also use !is_pointer, is_integral, or some other combination of type traits to allow for some other argument types but not char const*.

Or, as another alternative, you might eschew bool altogether and use your own enumeration with enumerators corresponding to true and false for the constructor. Whether this makes sense depends on your use case.

Declaring explicit T(const bool) to avoid does not solve the above problem...why is the form T t("") is still allowed and does call T(const bool)?

explicit only disallows implicit conversions to T. T t(""); has no conversions to T at all; it directly initializes the object t by constructing it with the argument "" passed to whichever constructor matches best.

那请放手 2024-12-06 22:48:31

"" 可以转换为 std::stringbool

问题是,它会以哪种方式转换?

  • std::string 的转换是用户定义的转换。
  • 转换为 bool 是标准转换。

所以答案是,标准转换比用户定义的转换具有更高的优先级。因此 "" 将转换为 bool

示例,

struct A
{
   A(int i) {} //i.e an int can implicity convert to A
};

void f(const A &) { cout << "User-defined conversion won" << endl; }
void f(const bool &) { cout << "Standard conversion won" << endl; }

int main() {
        f (10);
        return 0;
}

输出:

Standard conversion won

在线演示: http://www.ideone.com/5Bt0K

在上面的演示中, 10 可以转换为 Abool 两者。由于转换为 bool 是标准转换,因此它会转换为 bool,而不是 A

"" can convert to both std::string and bool.

The question is, which way will it convert?

  • Conversion to std::string is a user-defined conversion.
  • Conversion to bool is a standard conversion.

So the answer is, standard conversion has higher precedence over user-defined conversion. So "" will convert to bool.

Example,

struct A
{
   A(int i) {} //i.e an int can implicity convert to A
};

void f(const A &) { cout << "User-defined conversion won" << endl; }
void f(const bool &) { cout << "Standard conversion won" << endl; }

int main() {
        f (10);
        return 0;
}

Output:

Standard conversion won

Online demo : http://www.ideone.com/5Bt0K

In the above demo, 10 can convert to A and bool both. Since converting to bool is a standard conversion, it converts into bool, instead of A.

反话 2024-12-06 22:48:31

因为如果内置转换可用,则不会考虑用户定义的转换。

使用第三个构造函数,该构造函数采用 const char*。没有更好的办法了。

Because a user-defined conversion is not considered if a built-in one is available.

Use the third constructor, one that takes const char*. There's no better way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文