问题
Given the hierarchy:
struct base {};
struct a : public base {};
struct b : public base {};
I want to fill vector<base*> vecBase
and vector<a*> aVec
with this function:
template <typename T>
void foo(T* bar) {
if (is_base_of_v<decltype(baseVec)::value_type, T>) baseVec.push_back(static_cast<decltype(baseVec)::value_type>(bar));
if (is_base_of_v<decltype(aVec)::value_type, T>) baseVec.push_back(static_cast<decltype(aVec)::value_type>(bar));
}
The problem here is that even though the static_cast
will never be performed unless it's legal; calls like these fail to compile:
int myInt;
b myB;
foo(&myInt);
foo(&myB);
I know that I can specialize foo
. Is that what I have to do here, or is there a way to tip the compiler off to the fact that the offending static_cast
s will never happen?
回答1:
static if is what you're looking for. It was originally proposed by N3329 on Jan-10-'12.
On Mar-16-'13 Bjarne Stroustrup, Gabriel Dos Reis, and Andrew Sutton put forward N3613 which stated of
static if
:
This proposal would do much more harm than good. Language features addressing these problems must not negatively affect the language and our ability to build tools around it. We conclude that future development of
static if
should be abandoned, and that alternatives such as "concepts-lite" approach should be pursued instead.
The C++ Chicago Meeting on Sep-23-'13 the Concepts Study Group stated that they weren't including static if in their scope for the near future.
The Chicago Meeting did spawn Ville Voutilainen's simplification of
static if
: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4461.htmlThe C++ Lexena Meeting on May-4-'15 did discuss the simplification and encouraged the original authors to come back to the C++ Kona meeting on Oct-19-'15
In the C++ Kona Meeting Herb Sutter personally presented static if. He recounts that,
The feedback in the room, even Bjarne, was potentially interested in it from the point of view: This may be the only way to get a version of Concepts/Concepts Lite into C++17. There's no other way we'll get Concepts or anything like it into this major revision of the standard. So this is early days yet, but it has been presented. There is some interest. We now need to follow up and these things do take time and several cycles, but it is being proposed.
But for now you're going to have to specialize your templates:
template <typename T>
enable_if_t<negation_v<is_base_of<base, T>>, void> push(T*) {}
void push(base* i) {
baseVec.push_back(static_cast<decltype(baseVec)::value_type>(i));
}
void push(a* i) {
baseVec.push_back(static_cast<decltype(baseVec)::value_type>(i));
aVec.push_back(static_cast<decltype(aVec)::value_type>(i));
}
来源:https://stackoverflow.com/questions/37545078/do-i-have-to-specialize-templates-if-their-offending-code-is-in-an-iffalse