Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
478 views
in Technique[技术] by (71.8m points)

c++ - “Overload” function template based on function object operator() signature in C++98

I want to make a template function that takes a function and a vector and uses the function to map that vector to another vector that will be returned by the function template.

If the function taken as an argument is a free function, it may have one of two signatures.

// T is the parameter of the function template
T sig1(const T x);
T sig2(const T x, const std::vector<T>& v);

It may also be a function object in which operator() would behave like the free functions. Use of the function template for any of the 4 possibilities should be transparent.

std::vector<int> v;
// ... fill v somehow ...

// foo is either free function or function object instance
const std::vector<int> a = map_vec(foo, v);

I asked how to do this for C++11 and got a great answer from 0x499602D2.

"Overload" function template based on function object operator() signature

0x499602D2's answer makes use of the fact that these are two distinct template signatures in C++11:

template<typename F, typename T>
auto map_vec(F&& fnc, const std::vector<T>& source)
    -> decltype(void(fnc(std::declval<T>())), std::vector<T>{});

template<typename F, typename T>
auto map_vec(F&& fnc, const std::vector<T>& source)
    -> decltype(void(fnc(std::declval<T>(), source)), std::vector<T>{});

I would also like to know how to solve this in C++98.

Here is my effort so far. I have a SFINAE struct that can determine if a function objects takes two args. I don't know how to get this working for both function objects and free functions. Either I need to change the SFINAE struct to work on both function objects and free functions or I need to use overloading to route function objects and free functions separately.

http://coliru.stacked-crooked.com/a/1471088cbc3b8544

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here's my approach:

template <std::size_t, typename T = void> struct ignore_value {typedef T type;};

template <typename T>
T& declval();

template<typename F, typename T>
typename ignore_value<sizeof(declval<F>()(declval<T const>())),
       std::vector<T> >::type map_vec(F fnc, const std::vector<T>& source);

template<typename F, typename T>
typename ignore_value<sizeof(declval<F>()
                         (declval<T const>(), declval<const std::vector<T> >())),
       std::vector<T> >::type map_vec(F fnc, const std::vector<T>& source);

It works with the same Demo that 0x499602D2 used, with both GCC and Clang in C++98 mode.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...