为什么关键字`explicit`不适用于函数参数?

3
在某些情况下,可能不希望进行隐式类型转换。
例如:
#include <string>

using namespace std;

void f(bool)
{}

void f(string)
{}

int main()
{
    auto p = "hello";
    f(p); // Oops!!! Call void f(bool); rather than void f(string);
}

如果C++标准支持关键字explicit可以用于限定函数参数,代码可更改如下:
#include <string>

using namespace std;

void f(explicit bool) // Illegal in current C++11 standard!
{}

void f(string)
{}

int main()
{
    auto p = "hello";
    f(p); // Call void f(string);

    bool b = true;
    f(b); // Call void f(bool);

    f(8); // Error!
}

为什么C++标准不支持这样一个方便的功能?

我不明白。const char*std::string更适合于bool。前者是一个简单的构造,而后者则不是。所以你试图解决的问题是什么? - WhozCraig
在这种情况下,我不想将 const char* 隐式转换为 bool,该怎么办?换句话说,如果我想要禁用传递参数时的隐式类型转换,该怎么做? - xmllmx
所以你不想将其隐式转换为bool,但是你确实希望将其隐式转换为std::string?这就是关键吗? - WhozCraig
2
如果人们经常遇到这个问题,并且现有的解决方法不够令人满意,那么它可能有合理的机会被投票纳入标准。但我认为两者都不是这种情况,“优雅”也不是向已经有超过1300页的语言标准添加更多功能的好理由。 - Brian Bi
5
想要这样做其实是在暗示你可能不适当地使用了函数重载。f 函数做什么使得它可以接受 bool 或者 string 参数,并且可以用相同的逻辑进行处理呢? - Jerry Coffin
显示剩余3条评论
1个回答

4
#include <string>
#include <type_traits>      // std::is_same
#include <utility>          // std::enable_if
using namespace std;

template< class Value >
struct Explicit_
{
    Value    value;

    operator Value() const { return value; }

    template<
        class Arg,
        class Enabled = typename enable_if< is_same< Arg, Value >::value, void >::type
        >
    Explicit_( Arg const v ): value( v ) {}
};

void f( Explicit_<bool> ) // Valid in current C++11 standard!
{}

void f( string )
{}

int main()
{
    auto p = "hello";
    f(p); // Call void f(string);

    bool b = true;
    f(b); // Call void f(bool);

    f(8); // Error!
}

我知道这个技巧,但我认为这个技巧有一个缺点:考虑Explicit_<T>,如果类T的复制成本很高,那么会发生双重复制。此外,我认为void f(explicit bool)更具表现力,并且应该直接得到标准支持。 - xmllmx
1
@xmllmx:如果担心复制成本,那就避免复制。;-)也就是说,用引用而不是值进行包装。 - Cheers and hth. - Alf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接