【问题标题】:C++ explicit char/short?C++ 显式字符/短?
【发布时间】:2012-07-11 10:16:02
【问题描述】:

我想将一个字符传递给我的函数 (fn)。我不希望将整数和短裤类型转换到其中。所以我认为我应该将值隐式转换为 MyInt(仅支持 char)然后传递给 fn。这应该可以工作,因为 IIRC 在传递给函数时只允许一个类型转换(所以 char->MyInt 可以,而 int->char->MyInt 不应该)。

但是它看起来 int 和 char 都可以工作,所以我认为另一层间接(MyInt2)可以解决它。现在它们都不能传递给 fn... 有没有一种方法可以让我传递 chars 但不能传递 int?

#include <cstdio>
struct MyInt2{
    int v;
    MyInt2(char vv){v=vv;}
    MyInt2(){}
};
struct MyInt{
    MyInt2 v;
    MyInt(MyInt2 vv){v=vv;}
};
void fn(MyInt a){
    printf("%d", a.v);
}
int main() {
    fn(1);       //should cause error
    fn((char)2); //should NOT cause error
}

【问题讨论】:

  • 您是否在寻找编译或运行时错误?

标签: c++


【解决方案1】:

Function templates to the rescue:

template<typename T> void fn(T t);

void fn (char a){
    printf("%c", a);
}

如果有人尝试使用 char 以外的任何参数调用 fn,则函数模板将被选为匹配项,并且链接器将抱怨找不到合适的特化。

【讨论】:

  • 答案也很好。我不能在你们两个之间选择:X
  • 大声笑+1。那可能是他的,你知道的。如果假设我有 2 个函数或 3 个函数需要这个 ;)
  • @gwiazdorrr:不,他们不是(你到底是怎么从 Sutter 的文章中得出这个结论的?!?)。它们可能会被误用,这正是 Sutter 想要提出的观点,但在这种情况下,模板是一个非常合适的解决方案,因为不会有任何其他专业化(部分或不)。
  • @Jon:显然这是一种幽默的夸张,但 Suter 明确指出,您可以通过更喜欢重​​载而不是专业化来避免问题(重要道德和总结)。在这个特定的示例中,重载版本更短,一方面。它还有助于避免预先的问题。真的,在这里使用专业化有什么好处?
【解决方案2】:

您可以使用多态性并定义多个版本,一个接受int,一个接受short,然后抛出异常或导致断言失败,或隐藏构造函数:

struct MyInt2{
    int v;
    MyInt2(char vv){v=vv;}
    MyInt2(short s) { throw "short"; } /* exception, runtime error */
    MyInt2(){}
    private:
    MyInt2(int v) { } /* hidden, compile time error */
};

【讨论】:

  • 美丽。我知道 C++ 可以处理这个!
  • 乔恩的回答和这个一样好。我不能在你们两个之间选择:X
【解决方案3】:

您希望char 隐式转换为MyInt2,然后再转换为MyInt。但是语言规范不允许二级转换。

如果你想做一级隐式转换,那么C++11可以帮你。

在C++11中,你可以delete构造函数取int,允许取char的构造函数为:

struct MyInt{
    int v;

    MyInt(char vv) : v(vv) {} //use mem-initialization list

    MyInt(int) = delete;  //VALID only in C++11
};

注意带有intdeleted构造函数,它的意思是:

MyInt m1(10); //error - can't accept int!

MyInt m2((char)10); //okay - can accept char!

Online Demo

事实上,你可以delete所有构造函数,除了一个将char作为的构造函数:

struct MyInt{
    //..
    MyInt(char vv); //ALLOW
 
    template<typename T>
    MyInt(T) = delete;  //DELETED the rest!
};

Demo

了解更多:

希望对您有所帮助。

【讨论】:

  • 我不想这么说,但实际上你可以很容易地在 perreal 答案中发表评论说“或者你可以在 C++11 中使用 MyInt(int) = delete; 而不是将其设为私有”。反正+1
  • @acidzombie24:我为什么要发表评论,对于许多可能希望做类似事情的读者来说,这似乎是一个答案?评论不那么有价值,因为不是每个人都会阅读它们。我的回答包含了很好的信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 2013-07-20
  • 2011-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多