我怎样才能创建一个使用C ++ 11的风格强烈的typedef一个新的基本类型? [英] How can I create a new primitive type using C++11 style strong typedefs?

查看:323
本文介绍了我怎样才能创建一个使用C ++ 11的风格强烈的typedef一个新的基本类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在C ++ href=\"http://nim-lang.org/docs/manual.html#types-distinct-type\" rel=\"nofollow\">不同的一个 NIM型
编程语言。下面的例子将不
编译稔因为编译器捕获变量电子 D
具有不同类型(错误:类型不匹配:有(欧元,浮动)),尽​​管
两者都是一个浮动在二进制级别:

I'm trying to emulate in C++ a distinct type from the Nim programming language. The following example won't compile in Nim because the compiler catches the variables e and d having different types (Error: type mismatch: got (Euros, float)) despite both being a float at the binary level:

type
  Euros = distinct float

when isMainModule:
  var
    e = Euros(12.34)
    d = 23.3
  echo (e + d)

在C ++中这样做的一个方法是写彩车的包装类。 <击>但是,
这并不与出口型的API很好地工作,因为大小不会
是相同的浮动。甚至如果一个类大小的存储长度匹配
浮动,它永远不会匹配一个char类型的大小。,将工作,如果你还实现了所有可能的运营商喜欢此外,减法等操作,但需要大量的打字和code的重复。

One way to do this in C++ would be to write a wrapper class for floats. But this doesn't work well with APIs which export the type because the size won't be the same as float. Or even if a class' size matches the storage length of a float, it will never match the size of a char type. That will work if you also implement all possible operators for operations like addition, substraction, etc, but requires much typing and duplication of code.

旧的问题如创建新的原始
键入

有作为公认的答案使用boost强大的typedef。然而,的typedef
似乎只对函数类型签名工作,typedef的不会prevent 2
浮动继承类型加在一起和他们的类型完全改变
(一种新型的好,因为刚刚的幻觉的):

#include <boost/serialization/strong_typedef.hpp>
#include <stdio.h>

BOOST_STRONG_TYPEDEF(float, money);

void test(money a, float b)
{
    int t = a + b;
    printf("value is %d", t);
}

int main()
{
    money a(5.5);
    int euros(5);
    // This is not caught!
    int dollars = a + euros;
    printf("dollars %d\n", dollars);
    // But the compiler catches this misuse.
    test(euros, a);
}

但是,这是近吧,测试()调用不会因为签名工作
不匹配,但语言仍允许其它操作到裂伤类型
随意。

But that's nearly it, the test() call won't work because the signature doesn't match, but the language still allows other operations to mangle types at will.

这是同样的答案中提到的C ++ 0x带来强烈的typedef,所以我找了这个
新的支持和发现,<一个href=\"http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Keynote-Bjarne-Stroustrup-Cpp11-Style\"相对=nofollow> Bjarne的Stroustrup的自己给了C ++ 11的风格
在发表主题演讲
2012 。
大约21分钟,他开始谈论这些新的typedef强。如果你
SI单位的,后来仅下载幻灯片,第19页开始说起
第22页和23提及如何做到这一点来完成。不过,我一直无法
做例子的工作。这是我成功地炮制拼缝:

That same answer mentions C++0x to bring strong typedefs, so I looked for this new support and found that Bjarne Stroustrup himself gave a C++11 style keynote in 2012. Around minute 21 he starts talking about these new strong typedefs. If you download just the slides, page 19 starts talking about SI Units and later page 22 and 23 mention how this would be done. However, I have been unable to make the examples work. Here's the patchwork I managed to concoct:

template<int M, int K, int S> struct Unit { // a unit in the MKS system
    enum { m=M, kg=K, s=S };
};
template<typename Unit> // a magnitude with a unit
struct Value {
    double val; // the magnitude
    explicit Value(double d) : val(d) {} // construct a Value from a double
};

using Meter = Unit<1,0,0>; // unit: meter
using Second = Unit<0,0,1>; // unit: sec
using Speed = Value< Unit<1,0,-1> >; // meters/second type
constexpr Value<Second> operator "" _s(long double d)
// a f-p literal suffixed by ‘_s’
{
return Value<Second> (d);
}
constexpr Value<Meter> operator "" _m(long double d)
// a f-p literal suffixed by ‘_m’
{
return Value<Meter> (d);
}

int main(void)
{
    Speed sp1 = 100_m / 9.8_s;
    return 42;
}

我想用最新版的X code 5.1.1用命令行编​​译这个MacOSX的下:

I'm trying to compile this under MacOSX with the latest Xcode 5.1.1 with the command line:

$ g++ unit.cpp -std=c++11
unit.cpp:13:25: error: constexpr function's return type 'Value<Second>' is not a
      literal type
constexpr Value<Second> operator "" _s(long double d)
                        ^
unit.cpp:5:8: note: 'Value<Unit<0, 0, 1> >' is not literal because it is not an
      aggregate and has no constexpr constructors other than copy or move
      constructors
struct Value {
       ^
unit.cpp:18:24: error: constexpr function's return type 'Value<Meter>' is not a
      literal type
constexpr Value<Meter> operator "" _m(long double d)
                       ^
unit.cpp:5:8: note: 'Value<Unit<1, 0, 0> >' is not literal because it is not an
      aggregate and has no constexpr constructors other than copy or move
      constructors
struct Value {
       ^
unit.cpp:26:20: error: no matching literal operator for call to 'operator "" _m'
      with argument of type 'unsigned long long' or 'const char *', and no
      matching literal operator template
    Speed sp1 = 100_m / 9.8_s;
                   ^
unit.cpp:26:28: error: no matching literal operator for call to 'operator "" _s'
      with argument of type 'long double' or 'const char *', and no matching
      literal operator template
    Speed sp1 = 100_m / 9.8_s;
                           ^
4 errors generated.

也许在幻灯片中的例子,我错过了一些更code?是否有人有什么比亚试图展示一个完整的例子吗?

Maybe the examples given in the slides and I'm missing some more code? Does somebody have a complete example of what Bjarne was trying to demonstrate?

推荐答案

有几种方法来解决这个问题,但因为我是在presentation幻灯片寻找一个修复程序比亚的code,我接受这个答案而@ robson3.14留在评论的问题:

There are several ways to solve this, but since I was looking for a fix to Bjarne's code in the presentation slides, I'm accepting this answer which @robson3.14 left in comments to the question:

#include <iostream>

template<int M, int K, int S> struct Unit { // a unit in the MKS system
    enum { m=M, kg=K, s=S };
};

template<typename Unit> // a magnitude with a unit
struct Value {
    double val; // the magnitude
    // construct a Value from a double
    constexpr explicit Value(double d) : val(d) {} 
};

using Meter = Unit<1,0,0>; // unit: meter
using Second = Unit<0,0,1>; // unit: sec
using Speed = Value<Unit<1,0,-1>>; // meters/second type

// a f-p literal suffixed by ‘_s’
constexpr Value<Second> operator "" _s(long double d)
{
    return Value<Second> (d);
}
// a f-p literal suffixed by ‘_m’
constexpr Value<Meter> operator "" _m(long double d)
{
    return Value<Meter> (d);
}
// an integral literal suffixed by ‘_m’
constexpr Value<Meter> operator "" _m(unsigned long long d)
{
    return Value<Meter> (d);
}

template<int m1, int k1, int s1, int m2, int k2, int s2>
Value<Unit<m1 - m2, k1 - k2, s1 - s2>> operator / (Value<Unit<m1, k1, s1>> a, Value<Unit<m2, k2, s2>> b)
{
    return Value<Unit<m1 - m2, k1 - k2, s1 - s2>>(a.val / b.val);
}

int main()
{
    Speed sp1 = 100_m / 9.8_s;
    std::cout << sp1.val;
}

这篇关于我怎样才能创建一个使用C ++ 11的风格强烈的typedef一个新的基本类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆