我遇到了关于enable_if和模板特化的适当用法的问题.
修改示例后(出于保密原因),这是一个类似的例子:
我有一个名为"less"的函数,用于检查1st arg是否小于2nd arg.假设我想根据输入的类型有两种不同的实现 - 一个是整数实现,另一个是double.
到目前为止我的代码看起来像这样 -
#include <type_traits>
#include <iostream>
template <class T,
class = typename std::enable_if<std::is_floating_point<T>::value>::type>
bool less(T a, T b) {
// ....
}
template <class T,
class = typename std::enable_if<std::is_integral<T>::value>::type>
bool less(T a, T b) {
// ....
}
int main() {
float a;
float b;
less(a,b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面的代码没有编译,因为 - 它说我正在重新定义less方法.
错误是:
Z.cpp:15:19: error: template parameter redefines default argument
class = typename std::enable_if<std::is_integral<T>::value>::type>
^
Z.cpp:9:19: note: previous default template argument defined here …Run Code Online (Sandbox Code Playgroud) #include <type_traits>
struct A{};
struct B{};
template <typename T>
struct Foo
{
typename std::enable_if<std::is_same<T, A>::value>::type
bar()
{}
typename std::enable_if<std::is_same<T, B>::value>::type
bar()
{}
};
Run Code Online (Sandbox Code Playgroud)
错误信息:
14:5: error: 'typename std::enable_if<std::is_same<T, B>::value>::type Foo<T>::bar()' cannot be overloaded 10:5:
error: with 'typename std::enable_if<std::is_same<T, A>::value>::type Foo<T>::bar()'
Run Code Online (Sandbox Code Playgroud)
来源cpp.sh.我以为两者typename std::enable_if<std::is_same<T,?>::value>::type在同一时间都无效.
编辑
对于后人来说,这是基于@ KerrekSB答案的编辑 - SFINAE仅适用于推导出的模板参数
#include <type_traits>
struct A{};
struct B{};
template<typename T>
struct Foo
{
template<typename U = T>
typename std::enable_if<std::is_same<U,A>::value>::type
bar()
{
}
template<typename U = T>
typename std::enable_if<std::is_same<U,B>::value>::type
bar()
{
} …Run Code Online (Sandbox Code Playgroud) 场景:
我有多种类型可以归类为序列容器.
所有序列容器都是数据结构,但并非每个数据结构都是序列容器.
以下是代码中说明的示例.此示例中涉及的唯一"重要类型"是Array_T.它分为两类:它是一个序列容器,由于所有序列容器都是数据结构,因此它又是一个数据结构.
//A sequence container type
class Array_T{};
//A type trait for that particular sequence container
template <typename T> struct Is_Array { static const bool value = false; };
template <> struct Is_Array<Array_T> { static const bool value = true; };
//A type trait to identify all of the sequence containers
template <typename T> struct Is_A_Sequence_Container { static const bool value = Is_Array<T>::value
/* would probably "or" together more sequence types, but we only have Array_T in this …Run Code Online (Sandbox Code Playgroud) #include <iostream>
#include <cmath>
#include <type_traits>
template <typename T>
void f(T, T) // 1
{
std::cout << "Primary\n";
}
template <typename T>
void f(T, std::enable_if_t<std::is_floating_point_v<T>, T>) // 2
{
std::cout << "Special\n";
}
/*template <typename T>
std::enable_if_t<std::is_floating_point_v<T>> f(T, T) // 3
{
std::cout << "Special\n";
}*/
int main()
{
f(1.1, 1.1); // prints 'Primary'
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,std::enable_if应用于第二个函数模板重载的函数类型。该函数是通过 [T = double] 推导来调用的,并且它调用重载 1。但是,如果我注释掉重载 2 并将其替换为重载 3,那么编译器会抱怨该调用不明确。我也期望在第一种情况下,为什么编译器更喜欢重载 1 而不是 2?
我阅读了“函数模板重载”部分,但对我来说,重载 2 看起来更专业。
c++ language-lawyer enable-if function-templates-overloading
有机会使用enable_if类型转换运算符吗?看起来很棘手,因为返回类型和参数列表都是隐式的.
C++ 14将具有可以根据返回值推断出返回类型的函数.
auto function(){
return "hello world";
}
Run Code Online (Sandbox Code Playgroud)
我可以将此行为应用于通过返回类型惯用法对SFINAE 使用enable_if的函数吗?
例如,让我们考虑以下两个功能:
#include <type_traits>
#include <iostream>
//This function is chosen when an integral type is passed in
template<class T >
auto function(T t) -> typename std::enable_if<std::is_integral<T>::value>::type {
std::cout << "integral" << std::endl;
return;
}
//This function is chosen when a floating point type is passed in
template<class T >
auto function(T t) -> typename std::enable_if<std::is_floating_point<T>::value>::type{
std::cout << "floating" << std::endl;
return;
}
int main(){
function(1); //prints "integral"
function(3.14); …Run Code Online (Sandbox Code Playgroud) 我刚问了这个问题:std :: numeric_limits作为一个条件
我理解用于std::enable_if定义有条件地导致该方法无法编译的方法的返回类型的用法.
template<typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer, void>::type foo(const T &bar) { isInt(bar); }
Run Code Online (Sandbox Code Playgroud)
我不明白的是第二个参数和看似无意义的赋值,std::enable_if当它被声明为模板语句的一部分时,如Rapptz的 回答.
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
void foo(const T& bar) { isInt(); }
Run Code Online (Sandbox Code Playgroud) 我需要编写一个模板化函数,根据其参数的类别,它的行为会有所不同:
template<class ContainerType>
bool myFunc(ContainerType in){
//do some stuff
}
template<class NotAContainerType>
bool myFunc(NotAContainerType in){
//do something else
}
Run Code Online (Sandbox Code Playgroud)
我被限制在C++ 11中,所以static_if不在桌面上.此外,类的ContainerType和NotAContainerType非常大,并且可能在将来发生变化,因此只需手动添加一些例外作为模板特化也是不明智的.
我知道std::enable_if解决方法,但是如果我需要将它应用于两个相互不同的类集,我该如何使用它?
我试图创建一个类,它应该从其他类继承构造函数,但不从这些类本身继承.
在我的类初始化期间的某个时刻,我想使用完美转发来创建一个类型的对象,其构造函数与给定的参数匹配.
除了没有参数的默认构造函数之外,不存在歧义.
这是我的代码:
#include <string>
using namespace std;
//NOTE: this class is just an example to demonstrate the problem
class String {
public:
//default constructor to prevent ambiguity
String() {}
//construct from wstring
template<typename... Args>
String(enable_if<is_constructible<wstring, Args...>::value, Args>::type&&... args) : ws(forward<Args>(args)...) {}
//construct from string
template<typename... Args>
String(enable_if<is_constructible<string, Args...>::value, Args>::type&&... args) : s(forward<Args>(args)...) {}
private:
string s;
wstring ws;
};
void foo(const String& string) {
}
int main()
{
foo(L"123");
foo("123");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我尝试过很多东西,但我无法让它发挥作用.
enable_if无法自动扣除模板args(我认为)如果用户将函数指针作为参数传递,我想使用SFINAE来启用特定模板.
我用谷歌搜索但没有发现任何东西 - 我也尝试查看<type_traits>文档,但找不到任何类似的东西is_function_ptr<T>.
通过函数指针,我的意思是全局函数指针,比如TReturn(*)(TArgs...).