[SFINAE和函数重载时的隐式转换

问题描述 投票:1回答:1

我正在尝试编写一个模板帮助程序,该工具可以让我检查一组类型是否与结构成员的类型匹配。到目前为止,我已经写了这个-

#include <iostream>
#include <functional> 

struct foo {
    int field1;
    int field2;
};


template <typename...T, std::size_t ...indices >
constexpr bool construct (std::index_sequence<indices...>) {
    foo s = {std::get<indices>(std::tuple<T...>())...};
    return true;
}

template<typename...T>
static bool allowed(int) {
    construct<T...>(std::index_sequence_for<T...>());
    return true;
}

template<typename...T>
static bool allowed(long) {
    return false;
}

int main() {
    std::cout << allowed<int, int, int>(0); 
    return 0;
}

这里,对allowed<int, int, int>的调用显然无效,因为无法调用结构(foo有2个成员,并且正在用3初始化)。但是还有allow的另一种实现,它以long作为参数。从SFINAE开始,编译器是否不应该简单地匹配allow和return false的第二个模板实现?但是它给了我一个错误-

错误:“ foo”的初始化程序太多

foo s = {std::get<indices>(std::tuple<T...>())...};

[如果我只是注释掉allow的第一个实现,那么所有单词都可以,并且我得到了错误。我很困惑模板替换如何与隐式强制转换和函数重载交互。如果不允许这样做,是否有办法可以达到相同的效果?

c++ variadic-templates sfinae
1个回答
0
投票

foo在即时上下文之外,因此您将获得硬错误而不是SFINAE。考虑一下:

#include <iostream>
#include <functional>

struct foo {
    int field1;
    int field2;
};

template <typename U, typename...T, std::size_t ...indices >
constexpr auto construct (std::index_sequence<indices...>) -> decltype(new U {std::get<indices>(std::tuple<T...>())...}) {
    return nullptr;
}

template<typename...T, typename Q = decltype(construct<foo, T...>(std::index_sequence_for<T...>()))>
static bool allowed(int) {
    return true;
}

template<typename...T>
static bool allowed(long) {
    return false;
}


int main() {
    std::cout << "allowed<int,int>(0) = " << allowed<int,int>(0) << std::endl;
    std::cout << "allowed<int,int,int>(0) = " << allowed<int,int,int>(0) << std::endl;
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.