除非 T::answer 是整数类型,否则如何强制模板替换失败?
How to force template substitution failure unless T::answer is in integral type?
我有以下代码:
#include <type_traits>
struct SA {};
struct SB { static const int answer = 42; };
const int SB::answer;
template <typename T>
int F() {
return T::answer;
}
int main(int argc, char **argv) {
(void)argc; (void)argv;
// F<SA>(); // I want to make this a template substitution failure.
return F<SB>(); // This should still work.
}
我想让调用F<SA>()
成为模板替换失败。我已尝试将 int F
更改为 typename std::enable_if<std::is_integral<T::answer>::value, int>::type F
,但出现以下错误:
$ g++ --versiong++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
$ g++ -W -Wall -Wextra -Werror -std=c++0x -fno-diagnostics-show-caret ei.cc && ./a.out
ei.cc:8:55: error: to refer to a type member of a template parameter, use ‘typename T:: answer’ [-fpermissive]
ei.cc: In function ‘int main(int, char**)’:
ei.cc:16:20: error: no matching function for call to ‘F()’
ei.cc:16:20: note: candidate is:
ei.cc:8:76: note: template<class T> typename std::enable_if<std::is_integral<typename T::answer>::value, int>::type F()
ei.cc:8:76: note: template argument deduction/substitution failed:
ei.cc: In substitution of ‘template<class T> typename std::enable_if<std::is_integral<typename T::answer>::value, int>::type F() [with T = SB]’:
ei.cc:16:20: required from here
ei.cc:8:76: error: no type named ‘answer’ in ‘struct SB’
这试图在 struct SB
中查找名为 answer
的类型,但我想让它在 struct SB
中查找名为 answer
的整数字段。
添加 decltype(...)
似乎有效:将 int F
更改为 typename std::enable_if<std::is_integral<decltype(T::answer)>::value, int>::type F
。
我发现将 enable_if
检查放在模板参数中会使您的界面更加清晰:
template <typename T,
std::enable_if_t<std::is_integral<decltype(T::answer)>::value>* = nullptr>
int F() {
return T::answer;
}
或者更清楚,使用 R. Martinho Fernandes 的 Remastered enable_if。
namespace detail {
enum class enabler {};
}
template <typename Condition>
using EnableIf = std::enable_if_t<Condition::value, detail::enabler>;
template <typename T, EnableIf<std::is_integral<decltype(T::answer)>>...>
int F() {
return T::answer;
}
我有以下代码:
#include <type_traits>
struct SA {};
struct SB { static const int answer = 42; };
const int SB::answer;
template <typename T>
int F() {
return T::answer;
}
int main(int argc, char **argv) {
(void)argc; (void)argv;
// F<SA>(); // I want to make this a template substitution failure.
return F<SB>(); // This should still work.
}
我想让调用F<SA>()
成为模板替换失败。我已尝试将 int F
更改为 typename std::enable_if<std::is_integral<T::answer>::value, int>::type F
,但出现以下错误:
$ g++ --versiong++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
$ g++ -W -Wall -Wextra -Werror -std=c++0x -fno-diagnostics-show-caret ei.cc && ./a.out
ei.cc:8:55: error: to refer to a type member of a template parameter, use ‘typename T:: answer’ [-fpermissive]
ei.cc: In function ‘int main(int, char**)’:
ei.cc:16:20: error: no matching function for call to ‘F()’
ei.cc:16:20: note: candidate is:
ei.cc:8:76: note: template<class T> typename std::enable_if<std::is_integral<typename T::answer>::value, int>::type F()
ei.cc:8:76: note: template argument deduction/substitution failed:
ei.cc: In substitution of ‘template<class T> typename std::enable_if<std::is_integral<typename T::answer>::value, int>::type F() [with T = SB]’:
ei.cc:16:20: required from here
ei.cc:8:76: error: no type named ‘answer’ in ‘struct SB’
这试图在 struct SB
中查找名为 answer
的类型,但我想让它在 struct SB
中查找名为 answer
的整数字段。
添加 decltype(...)
似乎有效:将 int F
更改为 typename std::enable_if<std::is_integral<decltype(T::answer)>::value, int>::type F
。
我发现将 enable_if
检查放在模板参数中会使您的界面更加清晰:
template <typename T,
std::enable_if_t<std::is_integral<decltype(T::answer)>::value>* = nullptr>
int F() {
return T::answer;
}
或者更清楚,使用 R. Martinho Fernandes 的 Remastered enable_if。
namespace detail {
enum class enabler {};
}
template <typename Condition>
using EnableIf = std::enable_if_t<Condition::value, detail::enabler>;
template <typename T, EnableIf<std::is_integral<decltype(T::answer)>>...>
int F() {
return T::answer;
}