Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 别名到标准类型的自定义点_C++_Templates_Argument Dependent Lookup_Customization Point - Fatal编程技术网

C++ 别名到标准类型的自定义点

C++ 别名到标准类型的自定义点,c++,templates,argument-dependent-lookup,customization-point,C++,Templates,Argument Dependent Lookup,Customization Point,假设我正在lib命名空间中编写一些通用算法,用于调用自定义点my_func 第一次尝试是将ADL用于my_func 其中一个用户想专门为他的类型指定my_func,这是std类型的别名。当然,在他的名称空间中定义它是行不通的,因为ADL对alias不起作用。标准不允许在std命名空间中定义它。剩下的唯一选项似乎是在算法的名称空间lib中定义。但是,如果最终用户在包含自定义头之前包含算法头,那么这也不起作用 #include <iostream> #include <array&

假设我正在
lib
命名空间中编写一些通用算法,用于调用自定义点
my_func

第一次尝试是将ADL用于
my_func
其中一个用户想专门为他的类型指定
my_func
,这是
std
类型的别名。当然,在他的名称空间中定义它是行不通的,因为ADL对alias不起作用。标准不允许在
std
命名空间中定义它。剩下的唯一选项似乎是在算法的名称空间
lib
中定义。但是,如果最终用户在包含自定义头之前包含算法头,那么这也不起作用

#include <iostream>
#include <array>

// my_algorithm.hpp
namespace lib{

template<typename T>
void my_algorithm(const T& t){
    my_func(t);
}

} // namespace lib

// user1.hpp
namespace user1{

struct Foo1{
    // this is working as expected (ADL)
    friend void my_func(const Foo1&){
        std::cout << "called user1's customisation\n";
    }
};

} // namespace user1

// user2.hpp
namespace user2{

using Foo2 = std::array<int,1>;

// this won't work because Foo2 is actually in std namespace
void my_func(const Foo2&){
        std::cout << "called user2's customisation\n";
}

} // namespace user2

/* surely this isn't allowed
namespace std{
void my_func(const user2::Foo2&){
        std::cout << "called user2's customisation\n";
}
} //namespace std
*/

// another attempt to costomize in the algorithm's namespace
// this won't work because my_func isn't seen before my_algorithm
namespace lib{
    void my_func(const user2::Foo2&){
        std::cout << "called user2's customisation\n";
    }
}



// main.cpp
// #include "algorithm.hpp"
// #include "user1.hpp"
// #include "user2.hpp"
int main(){
    lib::my_algorithm(user1::Foo1{});
    lib::my_algorithm(user2::Foo2{});
}

为什么这个问题与第一个问题(原始ADL)不同?

第四个尝试是使用模板专业化,这似乎像预期的那样正常工作

#include <iostream>
#include <array>




// my_algorithm.hpp

namespace lib{

template<typename T, typename = void>
struct my_func_impl{
    //void static apply(const T&) = delete;
};

inline constexpr struct my_func_fn {
    
template <typename T>
void operator()(const T& t) const{
    using impl = my_func_impl<std::decay_t<T>>;
    impl::apply(t);
}

} my_func{};


template<typename T>
void my_algorithm(const T& t){
    my_func(t);
}

} // namespace lib

// user1.hpp
namespace user1{

struct Foo1{};

} // namespace user1

namespace lib{

template<>
struct my_func_impl<user1::Foo1>{
    void static apply(const user1::Foo1&){
        std::cout << "called user1's customisation\n";
    }
};

} //namespace lib



// user2.hpp
namespace user2{

using Foo2 = std::array<int,1>;

} // namespace user2

namespace lib{

template<>
struct my_func_impl<user2::Foo2>{
    void static apply(const user2::Foo2&){
        std::cout << "called user2's customisation\n";
    }
};

}



// main.cpp
int main(){
    lib::my_algorithm(user1::Foo1{});
    lib::my_algorithm(user2::Foo2{});
}
#包括
#包括


编写通用算法和自定义点并允许客户端自定义std类型别名的最佳方法是什么

其中一个用户想专门为他的类型指定
my_func
,这是std类型的别名

这是原罪,它给你带来了所有的痛苦。C++中的类型别名只是别名;他们不是新的类型。您有一个使用自定义点的通用算法,如

// stringify_pair is my generic algorithm; operator<< is my customization point
template<class T>
std::string stringify_pair(K key, V value) {
    std::ostringstream oss;
    oss << key << ':' << value;
    return std::move(oss).str();
}
另一个在做什么

using IntSet = std::set<int>;
template<> struct std::hash<IntSet> {
    size_t operator()(const IntSet& s) const { return s.size(); }
};
using IntSet = std::set<int>;
template<> struct std::hash<IntSet> {
    size_t operator()(const IntSet& s, size_t h = 0) const {
        for (int i : s) h += std::hash<int>()(i);
        return h;
    }
};
使用IntSet=std::set;
模板结构std::hash{
size\u t运算符()(常量IntSet&s,size\u t h=0)常量{
对于(inti:s)h+=std::hash()(i);
返回h;
}
};

然后,当您将
std::unordered_集
从一个对象文件传递到另一个对象文件时,他们都尝试使用
std::unordered_集
,然后在运行时出现boom、ODR冲突和未定义的行为,他们同意
std::hash
的名称,但不同意其含义。只是一大罐虫子。不要打开它。

请在问题中包含相关代码
struct OptionalInt {
    std::optional<int> data_;
    OptionalInt(int x) : data_(x) {}
    friend std::ostream& operator<<(std::ostream&, const OptionalInt&);
};
OptionalInt myvalue = 42;  // no problem now
using IntSet = std::set<int>;
template<> struct std::hash<IntSet> {
    size_t operator()(const IntSet& s) const { return s.size(); }
};
using IntSet = std::set<int>;
template<> struct std::hash<IntSet> {
    size_t operator()(const IntSet& s, size_t h = 0) const {
        for (int i : s) h += std::hash<int>()(i);
        return h;
    }
};