C++ SFINAE限定参数为自己定义的类
时间: 2024-05-12 09:13:48 浏览: 10
SFINAE(Substitution Failure Is Not An Error)是C++中的一种编译时技术,通过在编译期间对函数模板进行重载解析,来达到限制函数参数类型的目的。
如果我们想要限定参数为自己定义的类,可以使用std::enable_if结合std::is_same来实现。具体实现步骤如下:
1. 定义一个模板类,用于判断是否是我们定义的类:
```c++
template<typename T, typename = void>
struct is_my_class : std::false_type {};
template<typename T>
struct is_my_class<T, std::void_t<decltype(std::declval<T>().my_member)>> : std::true_type {};
```
2. 在模板函数中使用std::enable_if限定参数类型:
```c++
template<typename T, typename std::enable_if<is_my_class<T>::value, int>::type = 0>
void my_function(T t)
{
// do something
}
```
这样,当传入的参数类型不是我们定义的类时,编译器就会自动排除该函数模板,从而达到限制参数类型的目的。
相关问题
c++类函数参数为类 *
在C++中,类函数参数为类指针时通常用于指针传递。指针传递是一种传递变量地址的方式,通过传递指针,函数可以直接访问和修改实参所在的内存空间。通过在函数定义和声明时使用"*"来修饰形参,表示这个变量是指针类型。而在函数调用时,使用"&"来修饰实参,表示将该变量的地址作为参数传入函数。
举个例子,如果我们有一个类成员函数`void Fun(int *ptr)`,其中`ptr`是一个指向int类型的指针参数。在函数体内部,我们可以使用`*ptr`来访问和修改指针所指向的内存空间。在主函数中,我们可以通过使用`&`来获取实参的地址,并将其作为参数传递给函数`Fun`。这样,函数内部对指针的修改也会影响到实参的值。
```c++
#include <iostream>
using namespace std;
class MyClass {
public:
void Fun(int *ptr) {
cout << "形参指针ptr的地址 = " << ptr << endl;
*ptr = 100; // 对形参指针所指向的内存空间进行修改
}
};
int main() {
MyClass obj;
int a = 10;
cout << "实参a的地址 = " << &a << endl;
cout << "实参a的值 = " << a << endl;
obj.Fun(&a);
cout << "实参a的值 = " << a << endl;
return 0;
}
```
在上述代码中,我们创建了一个名为`MyClass`的类,并定义了其中的成员函数`Fun`,该函数接受一个指向int类型的指针参数`ptr`。在主函数中,我们创建了一个整型变量`a`,并将其地址传递给`Fun`函数。在函数内部,我们修改了指针所指向的内存空间的值,这也导致了实参`a`的值被修改为100。<span class="em">1</span><span class="em">2</span><span class="em">3</span>
#### 引用[.reference_title]
- *1* *2* *3* [C++函数参数中&和*的意义](https://blog.csdn.net/qq_34201858/article/details/104161539)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"]
[ .reference_list ]
C++ SFINAE基本语法
SFINAE (Substitution Failure Is Not An Error) 是一种 C++ 的模板机制,用于在编译时进行类型推导和函数重载选择。它的基本语法如下:
```
template <typename T>
struct has_typedef_foo {
typedef char yes[1];
typedef char no[2];
template <typename C>
static yes& test(typename C::foo*);
template <typename>
static no& test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
```
这个例子是用来判断一个类是否有名为 `foo` 的成员类型。它的实现利用了函数模板的重载和模板参数推导机制。
首先定义了两个类型 `yes` 和 `no`,分别占用 1 和 2 个字节。然后定义了两个静态函数模板 `test`,其中第一个版本使用了模板参数 `typename C::foo*`,并返回 `yes&` 类型;第二个版本使用了省略号,表示可以接受任意参数,但是返回 `no&` 类型。最后,在类中定义了一个静态常量 `value`,用来判断 `sizeof(test<T>(0))` 是否等于 `sizeof(yes)`,如果是,则表示类 `T` 中有成员类型 `foo`,否则没有。
在编译时,编译器会尝试将模板参数 `T` 替换到 `has_typedef_foo` 中,然后根据函数模板的重载规则选择调用哪个版本的 `test` 函数,如果模板参数推导失败,则选择第二个版本,返回 `no&` 类型。最后,通过比较 `sizeof(test<T>(0))` 是否等于 `sizeof(yes)` 来判断类 `T` 中是否有成员类型 `foo`。
需要注意的是,SFINAE 只适用于模板函数和模板类中的函数成员,对于非模板函数没有作用。此外,在使用 SFINAE 时需要注意错误处理,避免编译器报错。