如何获得C++ - 类似模板的行为,但只允许实例化两个特定类型?

Jer*_*ner 3 c++ templates

我试图从内联C++函数中获取特定类型的行为,我不确定是否有办法实现它.

我希望我的函数接受有符号或无符号的16位值作为参数,对该值执行操作,然后返回相同类型的值.如果参数的signed/unsigned-ness是不明确的(例如因为它是常量),那么编译器只需选择签名版本即可.这是一个玩具程序,显示我第一次尝试获取该行为:

 #include <iostream>
 #include <cstdint>

  int16_t getValuePlusOne( int16_t x) {return x+1;}
 uint16_t getValuePlusOne(uint16_t x) {return x+1;}

 using namespace std;

 int main(int, char **)
 {
     int16_t   signedVal = -15;
    uint16_t unsignedVal = 23;

    cout << getValuePlusOne(  signedVal) << endl;  // works, yay!
    cout << getValuePlusOne(unsignedVal) << endl;  // works, yay!
    cout << getValuePlusOne(1234)        << endl;  // COMPILE ERROR, ambiguous!  D'oh!
    return 0;
 }
Run Code Online (Sandbox Code Playgroud)

所以这几乎起作用,但它在getValuePlusOne(1234)上出错,因为1234是不明确的(它可以是有符号或无符号的).很公平,但我不想这样做.

所以这是我的第二次尝试:

#include <iostream>
#include <cstdint>

template <typename T> T getValuePlusOne(T val) {return val+1;}

using namespace std;

int main(int, char **)
{
    int16_t   signedVal = 5;
   uint16_t unsignedVal = 5;

   cout << getValuePlusOne(  signedVal) << endl;  // works, yay!
   cout << getValuePlusOne(unsignedVal) << endl;  // works, yay!
   cout << getValuePlusOne(1234)        << endl;  // works, yay!

   uint32_t inappropriateType32 = 54321;
   cout << getValuePlusOne(inappropriateType32) << endl;  // works, but I want this to be a compile-time error!  D'oh!

   float inappropriateTypeFloat = 666.0;
   cout << getValuePlusOne(inappropriateTypeFloat) << endl;  // works, but I want this to be a compile-time error!

   return 0;
}
Run Code Online (Sandbox Code Playgroud)

这个版本的工作方式就是我希望它能用于前三次调用getValuePlusOne() - 它们编译时没有错误,模板机制确保getValuePlusOne()的返回类型与其参数类型匹配,并选择默认参数/在模糊的情况下返回类型.好极了!

但是 - 这个版本还允许用户传入不适当的值(例如32位整数,甚至是 - gasp - 浮点类型),这在我的应用程序的上下文中没有意义,所以我想要编译器将这些调用标记为编译时错误,这种情况不会发生.

我有什么办法可以吃蛋糕吗?

nak*_*iya 5

这样的事情怎么样?

template <typename T> T getValuePlusOne(T val)
{
    static_assert(std::is_same<T, int16_t>::value || std::is_same<T, uint16_t>::value, "Incorrect type");
    return val+1;
}
Run Code Online (Sandbox Code Playgroud)

仍然,getValuePlusOne(1234)失败.但这不是因为类型不明确.这是因为Tint.