有没有办法强制用户显式指定模板参数类型

Is there a way to force the user to explicitly specify the template argument type?

本文关键字:类型 参数 用户 有没有      更新时间:2023-10-16

简短版本:我有一个模板函数,它是"通用的",但我想强制用户明确指定参数的类型,他们作为参数传递给这个函数。

有什么想法吗?


长版本:听起来像是一个糟糕的设计,但这是我的情况,我现在想不出更好的东西。

我正在尝试在一个小socket类中"实现"::setsockopt(我不想拥有大量的函数,采用不同的参数并做同样的事情)。例如:

template< typename OPTION_VALUE_TYPE >
bool set_option( int level, int option_name, const OPTION_VALUE_TYPE& value )
{
    return -1 != ::setsockopt( fd_, level, option_name, &value, sizeof( value ) );
}

但是,这可能会导致以下情况 - 使用 1 调用set_option,尝试设置unsigned char选项将导致失败,因为1 int。正确的用法是:

set_option< unsigned char >( level, option, 1 );

set_option( level, option, 1 );

将编译得很好,但会大错特错。

是的,您只需要以无法从参数推断的方式使用 template 参数。一种常见的方法是在模板类中使用 typedef:

template <typename T>
struct identity {
  typedef T type;
};
template <typename OPTION_VALUE_TYPE>
bool set_option(int level, int option_name,
                typename identity<const OPTION_VALUE_TYPE&>::type value);

要使用标准库中已存在的类型,可以使用enable_if

template <typename OPTION_VALUE_TYPE>
bool set_option(int level, int option_name,
                typename std::enable_if<true, const OPTION_VALUE_TYPE&>::type value);

这不允许类型参数推导的原因是编译器不能排除identity的特殊性:编译器不能排除你这样做

template <>
struct identity<U> { typedef V type; };

identity<U>::type将不再U.

将模板类型放在非推导上下文中,如下所示:

template <typename T> struct identity { using type = T; };
template <typename OPTION_VALUE_TYPE>
bool set_option(int level,
                int option_name,
                const typename identity<OPTION_VALUE_TYPE>::type& value);

强制用户显式传递类型参数以调用函数f的另一种方法是这样的。假设f是这样的:

template <typename T> void f(T a) { cout << a + 5 << endl };

你用别名参数重写它,T如下:

template <typename T, typename TT = T> void f(TT a) { cout << a + 5 << endl };

现在:

int main() {
  int a = 3;
  f<int>(a); // Instead the caller is forced to specify the type parameter
  // f(a); // This usage does not compile
}
<小时 />

对于您的特定函数set_option您需要将其重写为:

template<typename T, OPTION_VALUE_TYPE = T>
bool set_option(int level, int option_name, const T& value) {...}