数组向量的C++ SFINAE

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

我想做一个重载操作符<<,它只被容器(arrayvector)使用。

我有以下模板。

namespace reachability {
    template <typename Container>
    ostream& operator<<(ostream& out, const is_container<Container>(&container)) {
        string result = "{";

        for (values_t elem : container) {
            result += std::string(elem) + ",";
        }

        std::operator<<(out, result.substr(0, result.length() - 1) + "}");
        return out;
    }

    struct values_t {
        string type;
        operator std::string() const { return type; }
    };


    template<typename T, typename _ = void>
    struct is_container : std::false_type {};

    template<typename... Ts>
    struct is_container_helper {};

    template<typename T>
    struct is_container<
        T,
        std::conditional_t<
        false,
        is_container_helper<
        typename T::value_type,
        typename T::size_type,
        typename T::allocator_type,
        typename T::iterator,
        typename T::const_iterator,
        decltype(std::declval<T>().size()),
        decltype(std::declval<T>().begin()),
        decltype(std::declval<T>().end()),
        decltype(std::declval<T>().cbegin()),
        decltype(std::declval<T>().cend())
        >,
        void
        >
    > : public std::true_type{};

}

它被用在..:

reachability::values_t vals[5];

int main(int argc, char** argv)
{
    vals[0].type = "zoo";
    vals[1].type = "foo";
    vals[2].type = "loo";
    vals[3].type = "koo";
    vals[4].type = "moo";
    /*elements_t elems = { space::half };*/
    reachability::operator<<(cout, vals);
    return 0;
}

然而我得到一个错误,即没有重载操作符的实例与参数列表匹配。

如果我把操作符的模板改成:,我也有同样的问题。

ostream& operator<<(ostream& out, const Container (&container)[]) 

我只能通过这样做来解决这个问题。

ostream& operator<<(ostream& out, const Container (&container)) 
c++ sfinae
1个回答
2
投票

如果你想在函数声明时出现编译时错误,而不是在函数模板的主体被实例化时,你可以通过添加另一个模板参数来制作SFINAE,该模板参数的语法会被检查,如果它没有任何意义,编译器会告诉你,说 没有匹配的函数来调用...:

template <
  typename Container, 
  std::enable_if_t< is_container<Container>::value | 
                    std::is_array_v<Container> >* = nullptr>
ostream& operator<<(ostream& out, const Container&container ) {

如你所见,添加了第二个模板参数,它将是 void* = nullptr 只有在 Container 是一些支持 beginendsize 等,或者它是内置的数组类型(T []). 否则,编译器就会抱怨无法获得 type 用于申报 type* = nullptr.


std::vector<reachability::values_t> v;
std::list<reachability::values_t> l;
std::pair<int,int> p;
reachability::operator<<(cout, vals); // OK
reachability::operator<<(cout, v); // OK
reachability::operator<<(cout, l); // OK
reachability::operator<<(cout, p); // Wrong, compile-time error, no match ...

演示


1
投票

如果你想使用你定义的 is_container,使用

template<
typename Container, 
std::enable_if_t<is_container<Container>::value, int>= 0>
ostream& operator<<(ostream& out, const Container &container) {}

启用_if_t 将隐藏函数,使其免于基于boolean is_container<Container>::value. 请注意,您对 is_container 将接受收集

std::vector<reachability::values_t> vals(5);

而非数组

reachability::values_t vals[5];
© www.soinside.com 2019 - 2024. All rights reserved.