C++ C++;:将基类型完美透明地包装到类中?
我正在尝试开发一个类,它完美地包装了基类型,这样人们就可以像正常情况一样使用它们,同时也可以扩展它们/添加新功能(c++11/c++14/etc很好)。到目前为止我还没有成功。下面是我遇到的一个例子(这里我只实现了plus操作符,但我最终会实现它们):C++ C++;:将基类型完美透明地包装到类中?,c++,c++11,type-conversion,ambiguous,C++,C++11,Type Conversion,Ambiguous,我正在尝试开发一个类,它完美地包装了基类型,这样人们就可以像正常情况一样使用它们,同时也可以扩展它们/添加新功能(c++11/c++14/etc很好)。到目前为止我还没有成功。下面是我遇到的一个例子(这里我只实现了plus操作符,但我最终会实现它们): 模板 N类 { 公众: N(){}; N(int _var):var(_var){}; 模板 N运算符+(常数N&i)常数 {返回var+i;}; //#定义转换(x)模板::类型>运算符x()常量{return var;}; #定义转换(x)运
模板
N类
{
公众:
N(){};
N(int _var):var(_var){};
模板
N运算符+(常数N&i)常数
{返回var+i;};
//#定义转换(x)模板::类型>运算符x()常量{return var;};
#定义转换(x)运算符x()常量{return var;};
转换(bool);
转换(字符);
转换(无符号字符);
转换(短);
转换(无符号短);
换算(整数);
转换(无符号整数);
转换(长);
转换(无符号长);
转换(长-长);
转换(无符号长-长);
转换(浮动);
换算(双倍);
转换(长双);
T-var;
};
int main(int,char**)
{
N-n1;
n2;
int d=n1;
n1+n2;
返回0;
}
所以,基本上,正如你所看到的,我为它解释了一个基本的逻辑,在一系列条件中,类型之间的最小无损转换。但运行这个程序会得到:
test.cpp: In instantiation of ‘N<Return> N<T>::operator+(const N<Arg>&) const [with U = short int; Arg = int; Return = int; T = short int]’:
test.cpp:2542:8: required from here
test.cpp:2507:17: error: ambiguous overload for ‘operator+’ (operand types are ‘const short int’ and ‘const N<int>’)
{ return var+i; };
^
test.cpp:2507:17: note: candidate: operator+(int, int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, unsigned int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, long int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, long unsigned int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, long long int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, long long unsigned int) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, float) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, double) <built-in>
test.cpp:2507:17: note: candidate: operator+(int, long double) <built-in>
test.cpp:N::operator+(const N&)const[with U=short int;Arg=int;Return=int;T=short int]'的实例化:
测试。cpp:2542:8:从此处开始需要
test.cpp:2507:17:错误:“运算符+”的重载不明确(操作数类型为“const short int”和“const N”)
{返回var+i;};
^
测试cpp:2507:17:注:候选者:运算符+(int,int)
test.cpp:2507:17:注:候选者:运算符+(int,无符号int)
测试cpp:2507:17:注:候选者:运算符+(int,long int)
test.cpp:2507:17:注:候选者:运算符+(int,长无符号int)
测试cpp:2507:17:注:候选者:运算符+(int,long-long int)
test.cpp:2507:17:注:候选者:运算符+(int,long-unsigned int)
测试cpp:2507:17:注:候选:运算符+(int,float)
测试cpp:2507:17:注:候选者:运算符+(整数,双精度)
测试cpp:2507:17:注:候选者:运算符+(整数,长双精度)
…因为转换运算符都可以调用,所以编译器认为所有这些都是显式指定转换的同等有效选项。现在,如果我们切换到注释掉的转换宏,使每种类型只启用一个转换运算符,我们将得到:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:2541:11: error: cannot convert ‘N<short int>’ to ‘int’ in initialization
int d = n1;
^
test.cpp:在函数“int main(int,char**)”中:
test.cpp:2541:11:错误:无法在初始化时将“N”转换为“int”
int d=n1;
^
。。。因为编译器拒绝转换为short,然后将其转换为int,所以它需要显式的直接转换运算符
我清楚地知道,我可以通过在主函数中使用显式强制转换来实现这一点。但这不是重点,重点是透明包装,一个行为类似于基类型(不需要显式强制转换)的类
<> Pc>在C++中物理上是不可能的吗?(我想我每个人都明白了!这不是最漂亮的代码,但似乎很管用。首先,我要指出的是,我将问题分解为两种变体:“StrongNumber”,它试图始终返回包装好的数字类;以及“WeakNumber”,它总是试图返回一个基类型。关键是-是什么让它难看-避免使用模板。模板只会导致编译器混乱
template <class T>
class StrongNumber
{
public:
StrongNumber() {};
StrongNumber(const T& _var) : var(_var) {};
StrongNumber(const StrongNumber<T>& i) : var(i.var) {};
#define DECLARE_HELPER(x, y) \
auto operator x (const StrongNumber<long double>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<double>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<float>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<unsigned long long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<long long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<unsigned long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };\
auto operator x (const StrongNumber<long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<unsigned int>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<int>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<unsigned short>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<short>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<unsigned char>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };\
auto operator x (const StrongNumber<char>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<bool>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const long double i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const double i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const float i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const unsigned long long i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const long long i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const unsigned long i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const long i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const unsigned int i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const int i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const unsigned short i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const short i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const unsigned char i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const char i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const bool i) y { return StrongNumber<decltype(var x i)>(var x i); };
#define DECLARE(x) DECLARE_HELPER(x, )
#define DECLARE_CONST(x) DECLARE_HELPER(x, const)
#define DECLARE_UNARY(x) auto operator x () { return StrongNumber<decltype(x var)>(x var); };
#define DECLARE_UNARY_CONST(x) auto operator x () const { return StrongNumber<decltype(x var)>(x var); };
operator T() const { return var; };
DECLARE_CONST(%);
DECLARE_CONST(+);
DECLARE_CONST(-);
DECLARE_CONST(*);
DECLARE_CONST(/);
DECLARE_CONST(&);
DECLARE_CONST(|);
DECLARE_CONST(^);
DECLARE_CONST(<<);
DECLARE_CONST(>>);
DECLARE(=);
DECLARE(+=);
DECLARE(-=);
DECLARE(*=);
DECLARE(/=);
DECLARE(&=);
DECLARE(|=);
DECLARE(^=);
DECLARE(<<=);
DECLARE(>>=);
DECLARE_CONST(==);
DECLARE_CONST(!=);
DECLARE_CONST(>);
DECLARE_CONST(<);
DECLARE_CONST(>=);
DECLARE_CONST(<=);
DECLARE_UNARY(++);
DECLARE_UNARY(--);
DECLARE_UNARY_CONST(+);
DECLARE_UNARY_CONST(-);
DECLARE_UNARY_CONST(~);
DECLARE_UNARY_CONST(!);
explicit operator std::string() const { return std::to_string(var); };
static int size() { return sizeof(T); };
T var;
};
template <class T>
class WeakNumber
{
public:
WeakNumber() {};
WeakNumber(const T& _var) : var(_var) {};
WeakNumber(const WeakNumber<T>& i) : var(i.var) {};
#undef DECLARE_HELPER
#define DECLARE_HELPER(x, y) \
auto operator x (const WeakNumber<long double>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<double>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<float>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<unsigned long long>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<long long>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<unsigned long>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<long>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<unsigned int>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<int>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<unsigned short>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<short>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<unsigned char>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<char>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<bool>& i) y { return var x i.var; }; \
auto operator x (const long double i) y { return var x i; }; \
auto operator x (const double i) y { return var x i; }; \
auto operator x (const float i) y { return var x i; }; \
auto operator x (const unsigned long long i) y { return var x i; }; \
auto operator x (const long long i) y { return var x i; }; \
auto operator x (const unsigned long i) y { return var x i; }; \
auto operator x (const long i) y { return var x i; }; \
auto operator x (const unsigned int i) y { return var x i; }; \
auto operator x (const int i) y { return var x i; }; \
auto operator x (const unsigned short i) y { return var x i; }; \
auto operator x (const short i) y { return var x i; }; \
auto operator x (const unsigned char i) y { return var x i; }; \
auto operator x (const char i) y { return var x i; }; \
auto operator x (const bool i) y { return var x i; };
#undef DECLARE
#undef DECLARE_CONST
#undef DECLARE_UNARY
#undef DECLARE_UNARY_CONST
#define DECLARE(x) DECLARE_HELPER(x, )
#define DECLARE_CONST(x) DECLARE_HELPER(x, const)
#define DECLARE_UNARY(x) auto operator x () { return x var; };
#define DECLARE_UNARY_CONST(x) auto operator x () const { return x var; };
operator T() const { return var; };
DECLARE_CONST(%);
DECLARE_CONST(+);
DECLARE_CONST(-);
DECLARE_CONST(*);
DECLARE_CONST(/);
DECLARE_CONST(&);
DECLARE_CONST(|);
DECLARE_CONST(^);
DECLARE_CONST(<<);
DECLARE_CONST(>>);
DECLARE(=);
DECLARE(+=);
DECLARE(-=);
DECLARE(*=);
DECLARE(/=);
DECLARE(&=);
DECLARE(|=);
DECLARE(^=);
DECLARE(<<=);
DECLARE(>>=);
DECLARE_CONST(==);
DECLARE_CONST(!=);
DECLARE_CONST(>);
DECLARE_CONST(<);
DECLARE_CONST(>=);
DECLARE_CONST(<=);
DECLARE_UNARY(++);
DECLARE_UNARY(--);
DECLARE_UNARY_CONST(+);
DECLARE_UNARY_CONST(-);
DECLARE_UNARY_CONST(~);
DECLARE_UNARY_CONST(!);
// A couple more just because they're useful
explicit operator std::string() const { return std::to_string(var); };
static int size() { return sizeof(T); };
T var;
};
模板
类strong编号
{
公众:
StrongNumber(){};
StrongNumber(const T&_var):var(_var){};
StrongNumber(conststrongnumber&i):var(i.var){};
#定义DECLARE_HELPER(x,y)\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const StrongNumber&i)y{return StrongNumber(var x i.var);}\
自动运算符x(const long double i)y{return StrongNumber(var x i);}\
自动运算符x(const double i)y{return StrongNumber(var x i);}\
自动运算符x(常量浮点i)y{return StrongNumber(var x i);}\
自动运算符x(const unsigned long long i)y{return StrongNumber(var x i);}\
自动运算符x(const long long i)y{return StrongNumber(var x i);}\
自动运算符x(const unsigned long i)y{return StrongNumber(var x i);}\
自动运算符x(const long i)y{return StrongNumber(var x i);}\
自动运算符x(const unsigned int i)y{return StrongNumber(var x i);}\
自动运算符x(const int i)y{返回强数(var x i);}\
自动运算符x(const unsigned short i)y{return StrongNumber(var x i);}\
自动运算符x(const short i)y{return StrongNumber(var x i);}\
自动运算符x(常量无符号字符i)y{return StrongNu
template <class T>
class StrongNumber
{
public:
StrongNumber() {};
StrongNumber(const T& _var) : var(_var) {};
StrongNumber(const StrongNumber<T>& i) : var(i.var) {};
#define DECLARE_HELPER(x, y) \
auto operator x (const StrongNumber<long double>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<double>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<float>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<unsigned long long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<long long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<unsigned long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };\
auto operator x (const StrongNumber<long>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<unsigned int>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<int>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<unsigned short>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<short>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<unsigned char>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); };\
auto operator x (const StrongNumber<char>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const StrongNumber<bool>& i) y { return StrongNumber<decltype(var x i.var)>(var x i.var); }; \
auto operator x (const long double i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const double i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const float i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const unsigned long long i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const long long i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const unsigned long i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const long i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const unsigned int i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const int i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const unsigned short i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const short i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const unsigned char i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const char i) y { return StrongNumber<decltype(var x i)>(var x i); }; \
auto operator x (const bool i) y { return StrongNumber<decltype(var x i)>(var x i); };
#define DECLARE(x) DECLARE_HELPER(x, )
#define DECLARE_CONST(x) DECLARE_HELPER(x, const)
#define DECLARE_UNARY(x) auto operator x () { return StrongNumber<decltype(x var)>(x var); };
#define DECLARE_UNARY_CONST(x) auto operator x () const { return StrongNumber<decltype(x var)>(x var); };
operator T() const { return var; };
DECLARE_CONST(%);
DECLARE_CONST(+);
DECLARE_CONST(-);
DECLARE_CONST(*);
DECLARE_CONST(/);
DECLARE_CONST(&);
DECLARE_CONST(|);
DECLARE_CONST(^);
DECLARE_CONST(<<);
DECLARE_CONST(>>);
DECLARE(=);
DECLARE(+=);
DECLARE(-=);
DECLARE(*=);
DECLARE(/=);
DECLARE(&=);
DECLARE(|=);
DECLARE(^=);
DECLARE(<<=);
DECLARE(>>=);
DECLARE_CONST(==);
DECLARE_CONST(!=);
DECLARE_CONST(>);
DECLARE_CONST(<);
DECLARE_CONST(>=);
DECLARE_CONST(<=);
DECLARE_UNARY(++);
DECLARE_UNARY(--);
DECLARE_UNARY_CONST(+);
DECLARE_UNARY_CONST(-);
DECLARE_UNARY_CONST(~);
DECLARE_UNARY_CONST(!);
explicit operator std::string() const { return std::to_string(var); };
static int size() { return sizeof(T); };
T var;
};
template <class T>
class WeakNumber
{
public:
WeakNumber() {};
WeakNumber(const T& _var) : var(_var) {};
WeakNumber(const WeakNumber<T>& i) : var(i.var) {};
#undef DECLARE_HELPER
#define DECLARE_HELPER(x, y) \
auto operator x (const WeakNumber<long double>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<double>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<float>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<unsigned long long>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<long long>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<unsigned long>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<long>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<unsigned int>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<int>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<unsigned short>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<short>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<unsigned char>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<char>& i) y { return var x i.var; }; \
auto operator x (const WeakNumber<bool>& i) y { return var x i.var; }; \
auto operator x (const long double i) y { return var x i; }; \
auto operator x (const double i) y { return var x i; }; \
auto operator x (const float i) y { return var x i; }; \
auto operator x (const unsigned long long i) y { return var x i; }; \
auto operator x (const long long i) y { return var x i; }; \
auto operator x (const unsigned long i) y { return var x i; }; \
auto operator x (const long i) y { return var x i; }; \
auto operator x (const unsigned int i) y { return var x i; }; \
auto operator x (const int i) y { return var x i; }; \
auto operator x (const unsigned short i) y { return var x i; }; \
auto operator x (const short i) y { return var x i; }; \
auto operator x (const unsigned char i) y { return var x i; }; \
auto operator x (const char i) y { return var x i; }; \
auto operator x (const bool i) y { return var x i; };
#undef DECLARE
#undef DECLARE_CONST
#undef DECLARE_UNARY
#undef DECLARE_UNARY_CONST
#define DECLARE(x) DECLARE_HELPER(x, )
#define DECLARE_CONST(x) DECLARE_HELPER(x, const)
#define DECLARE_UNARY(x) auto operator x () { return x var; };
#define DECLARE_UNARY_CONST(x) auto operator x () const { return x var; };
operator T() const { return var; };
DECLARE_CONST(%);
DECLARE_CONST(+);
DECLARE_CONST(-);
DECLARE_CONST(*);
DECLARE_CONST(/);
DECLARE_CONST(&);
DECLARE_CONST(|);
DECLARE_CONST(^);
DECLARE_CONST(<<);
DECLARE_CONST(>>);
DECLARE(=);
DECLARE(+=);
DECLARE(-=);
DECLARE(*=);
DECLARE(/=);
DECLARE(&=);
DECLARE(|=);
DECLARE(^=);
DECLARE(<<=);
DECLARE(>>=);
DECLARE_CONST(==);
DECLARE_CONST(!=);
DECLARE_CONST(>);
DECLARE_CONST(<);
DECLARE_CONST(>=);
DECLARE_CONST(<=);
DECLARE_UNARY(++);
DECLARE_UNARY(--);
DECLARE_UNARY_CONST(+);
DECLARE_UNARY_CONST(-);
DECLARE_UNARY_CONST(~);
DECLARE_UNARY_CONST(!);
// A couple more just because they're useful
explicit operator std::string() const { return std::to_string(var); };
static int size() { return sizeof(T); };
T var;
};
template<class T1, class T2, class T3>
T3 foo()
{
StrongNumber<T1> n1;
StrongNumber<T2> n2;
T3 d = n1;
n1 + n2;
n1 + 1;
n1 + 1.0;
d = d + n1;
d += 1 + n1;
d += 1.0 + n1;
return d;
}
std::cout << foo<short, long long, int>() << std::endl;