具有不同类型的模板非类型参数

时间:2019-04-23 01:58:42

标签: c++ templates c++14 template-meta-programming sfinae

我们假设输入模板参数T可以具有或可以不具有内部变量bar。我正在尝试编写一个结构,该结构在有bar时返回值,而在没有时返回一些常量。这是我的尝试:

struct A {
  static constexpr unsgined int bar = 20;
  hasBar = true;
};

struct B {
  hasBar = false;
};

template <typename T, typename std::enable_if<T::hasBar, int>::type>
struct getBar {
  static constexpr unsigned int bar = T::bar;
};

template <typename T, typename std::enable_if<!T::hasBar, int>::type>
struct getBar {
  static constexpr unsigned int bar = 0;
};

int main() {
  getBar<A>::bar; // Expect 20
  getBar<B>::bar; //Expect 0
}

我无法使用C ++ 14编译此代码。编译器抱怨:“模板非类型参数具有不同的类型”。

为什么会有这样的错误,我该如何解决?

3 个答案:

答案 0 :(得分:3)

您可以检测是否::bar直接存在而无需hasbar

类似...

#include <type_traits>
#include <iostream>
struct A {
  static constexpr unsigned int bar = 20;

};

struct B {

};


template <typename T,typename=void>
struct getBar {
  static constexpr unsigned int bar = 0;
};

template <typename T>
struct getBar<T,std::void_t<decltype(T::bar)>> {
  static constexpr unsigned int bar =  T::bar;
};

int main() {
  std::cout << getBar<A>::bar << std::endl; // Expect 20
  std::cout << getBar<B>::bar << std::endl; //Expect 0
}

Demo

答案 1 :(得分:2)

类模板不能重载(如功能模板);您可以改用specialization。例如

template <typename T, typename = void>
struct getBar {
  static constexpr unsigned int bar = 0;
};

template <typename T>
struct getBar<T, std::enable_if_t<T::hasBar>> {
  static constexpr unsigned int bar = T::bar;
};

LIVE

答案 2 :(得分:2)

另一种不需要hasBar的解决方案,只需检测bar的存在(如果与bar不同,还可以保持int的原始类型)< / p>

struct A
 { static constexpr unsigned int bar = 20; };

struct B
 { };

template <typename T>
constexpr auto getBarHelper (int) -> decltype( T::bar )
 { return T::bar; }

template <typename T>
constexpr int getBarHelper (long)
 { return 0; }

template <typename T>
struct getBar
 { static constexpr auto bar { getBarHelper<T>(0) }; };

int main()
 {
   static_assert( 20u == getBar<A>::bar, "!" );
   static_assert(  0  == getBar<B>::bar, "!" );
 }