如何限制模板中的类型名称

时间:2016-02-06 14:41:52

标签: c++

有一个可以接受4种不同类型的功能。它们的实现非常相似。

template< typename T >
void foo( std::string &&name, T value ){
    //...
}

typename T必须是4种预定义类型之一。其他类型名称是不可接受的,应在编译时加以限制 是否可以用C ++编写?

3 个答案:

答案 0 :(得分:5)

我至少可以想到三种方式,不管怎么说。

首先:

namespace internal {
template< typename T >
void foo_impl( std::string &&name, T value ) {
    // actual implementation here
}
}

void foo(std::string &&name, SpecialType1 value ) {
    internal::foo_impl(std::forward<std::string>(name), value);
}
void foo(std::string &&name, SpecialType2 value ) {
    internal::foo_impl(std::forward<std::string>(name), value);
}

第二

template< typename T >
typename std::enable_if<std::is_same<T, SpecialType1>::value ||
                        std::is_same<T, SpecialType2>::value >::type
foo( std::string &&name, T value ){
    //implementation here
}

第三

template< typename T >
void foo(std::string &&name, T value){
    static_assert(std::is_same<T, SpecialType1>::value ||
                  std::is_same<T, SpecialType2>::value,
    "wrong template argument");
    //implementation here
}

Demo

答案 1 :(得分:1)

我看到人们做过的一件事就是使用std::enable_if。我不确切知道您的4种类型是什么,因此这是一个包含intfloat两种类型的示例。

using myType = std::enable_if<
std::is_same<int, T>::value ||
std::is_same<float, T>::value, T >::type;

myType仅在T完全是intfloat时才存在。希望有所帮助!

答案 2 :(得分:1)

<type_traits>让您将逻辑推广到类模板中。这是如何工作的我们采用模板参数T和参数包Ts,我们开始检查T是否与类型列表的Head相同。如果找到匹配,我们继承std::true_type,我们就完成了。如果找不到匹配项,我们会弹出头部并以Ts的尾部递归实例化相同的模板。最终,如果根本找不到匹配项,参数包大小将降至零,编译器将实例化从std::false_type继承的基本模板类。请更好地查看video以及Walter E. Brown先生的部门解释。

template<class T, class...> struct is_any_of: std::false_type{};
template<class T, class Head, class... Tail> 
struct is_any_of<T, Head, Tail...>: std::conditional_t<
  std::is_same<T, Head>::value, 
  std::true_type,
  is_any_of<T, Tail...>>
{};

现在我们可以使用enable_if几乎用英文写法来完成SFINAE。

#include <type_traits>
#include <string>

template<
  class T,
  class = std::enable_if_t<is_any_of<T, int, float, unsigned, double>::value>
>
void foo(std::string &&str, T value) {}


int main()
{
  foo(std::string{"hello"}, 3);
  foo(std::string{"world"}, '0'); //compile-time error
}

SFANIE是一种语言功能,一种工具,用于或滥用有人说要实现你的要求,

  

标准库组件std :: enable_if允许创建替换失败,以便根据在编译时评估的条件启用或禁用特定的重载。   仅供参考http://en.cppreference.com/w/cpp/language/sfinae

请注意,std::conditional_t<>std::enable_if_t<>分别来自std::conditional<>::typestd::enable_if<>::type。您可以在代码中简单地替换这些,但应在typename之前添加enable_if关键字。