在构造函数中使用SFINAE,检查成员类型的构造函数是否存在

问题描述 投票:0回答:1
#include <string>
#include <type_traits>

struct A {
    A(int) {}
};

template<typename... Args>
auto make_A(const Args&... args) -> decltype(A(args...)) {
    return A(args...);
}

struct B {
    template<typename... Args
        //std::enable_if ?
    >
    B(const Args&... args) : a(args...) { } 
    
    A a;
};


int main() {
    A a1 = make_a(123);
    //A a2 = make_a(std::string("123")); // no make_a<std::string>
    
    B b1(123); // ok 
    B b2(std::string("123")); // fails because A(std::string) does not exist,
                              // but should fail already because there is no B(std::string)
}

在这样的代码中

A
只能用
int
参数来构造。

make_a
使用 SFINAE,因此仅当
make_a<Args...>
存在时才实例化
A::A(Args...)
。它在返回类型中使用
decltype()
来执行此操作,其中
args
可用。

是否也可以以类似的方式限制模板化构造函数

B::B<Args...>
?这里,SFINAE 触发表达式只能出现在模板参数中。

c++ templates constructor sfinae
1个回答
0
投票

SFINAE 在表达式上最简单的位置是 noexcept 说明符:

struct B {
    template<typename... Args>
    B(const Args&... args) noexcept(noexcept(A(args...))) : a(args...) { } 
    // `noexcept(false && noexcept(A(args...)))` if you need to keep it `noexcept(false)` for whatever reason
    A a;
};

在 C++20 中,您可以使用约束和需求表达式来做到这一点:

struct B {
    B(const auto&... args) requires(requires { A(args...); }) : a(args...) { }
    A a;
};
© www.soinside.com 2019 - 2024. All rights reserved.