3

In C++ there are SFINAE tricks to get at compile-time if a class has a named field, typedef or method.

My question is: can we also somehow query if a method is accessible? Like distinguish between private and public methods.

For example if I have a class privately inheriting from std::vector like class T : private std::vector<int> { ... }; I don't want to detect its begin method since it's not publicly accessible.

When seraching arround I only get code to detect a method, nothing about visibility... The closest I got was this which addressed inherited methods but it's not clear how it interacts with visibility. Obviously I could test, but I'm concerned with compiler-specific behavior, since I'm working on a project on old Microsoft's compilers :\

Edit / clarification : It says here that the C++ standard changed its view on this issue: with C++03 any visible or invisible member is substitutable, but since C++11 only visible members are. Is this correct ?

I did some testing with the code below which detects the value_type typedef. I'm not sure what the standard says, but I compiled with different compilers and here's the result:

  • gcc : 4.4 true | 4.5 true | 4.6 true | 4.7 true | 4.8 false | pre-4.9 false
  • Clang : 3.3 fail
  • icc : 13 true
  • msvc : 2005 true | 2010 true | 2012 true

Here's the code:

#include <vector>

typedef char yes;
typedef int no;

template<class T> struct has_value_type {
   template<class U> static yes test(typename U::value_type*);
    template<class U> static no  test(...);
    static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};

class C : private std::vector<int> {  };

int main() {
   return has_value_type<C>::value;
}
Community
  • 1
  • 1
Antoine
  • 13,494
  • 6
  • 40
  • 52
  • If a sfinae check of method being present succeeds, it should also mean that this method is public (otherwise calling it during sfinae checks would result in a sfinae failure), isn't it? – lisyarus Mar 03 '14 at 18:08
  • @lisyarus: I'm not sure about that... guess that's what I'm asking ;) – Antoine Mar 03 '14 at 18:08
  • 2
    Relevant: http://stackoverflow.com/questions/8984013/can-sfinae-detect-private-access-violations – chris Mar 03 '14 at 18:10
  • What exactly are you trying to do? Replacing `#ifdef`'s with SFINAE? What are your alternatives if a method isn't public as you expect? The compiler will already tell you if the function isn't public and you're going to access it, not need for extra checks IMHO. – πάντα ῥεῖ Mar 03 '14 at 18:11
  • @chris: indeed [...] Note: Access checking is done as part of the substitution process. – Antoine Mar 03 '14 at 18:11
  • 2
    Here's something you can use to test it: http://coliru.stacked-crooked.com/a/630e969edc491662 – chris Mar 03 '14 at 18:13
  • Notwithstanding the answers in the thread referenced by Chris, I have yet to see any **concrete example** that works and can be tested. I would love this functionality. E.g. in order to test for a publicly accessible `size` function. I think if it was really possible then such an example would have been known to me, since I tend to ask about things. – Cheers and hth. - Alf Mar 03 '14 at 18:14
  • @πάνταῥεῖ: For performance reasons I reimplemented a class which has to be convertible to/from many other classes; I added a template constructor to my class, but incompatible classes trigger visibility errors. I wnated to know if adding `enable_if` on this constructor was a portable solution. – Antoine Mar 03 '14 at 18:15
  • @Cheersandhth.-Alf: I'm quite busy at work but if nothing definite comes up I'll do some testing on many compilers and post it here. – Antoine Mar 03 '14 at 18:18
  • 1
    [This answer](http://stackoverflow.com/a/16824239/947836) of mine could be of help. The check reports false if the function can't be called for whatever reason. Pre C++11, it think this is impossible. – jrok Mar 03 '14 at 22:46
  • @jrok: thanks. there is one fly in the ointment though. namely, that mainline visual c++ doesn't yet support `constexpr`. however, the [november 2013 ctp](http://blogs.msdn.com/b/vcblog/archive/2013/11/18/announcing-the-visual-c-compiler-november-2013-ctp.aspx) provides support except for member functions. which reminds that i better download and install that. – Cheers and hth. - Alf Mar 03 '14 at 23:57
  • @jrok thanks that's good, unfortunately I'm stuck with C++03 for this project. Still interesting though! – Antoine Mar 04 '14 at 07:20
  • I added tests results illustrating my problem : is there a portable consistent solution ? – Antoine Mar 05 '14 at 12:53
  • 2
    Access checking is done during substitution, but only since C++11. C++03 explicitly said access check is not done. Therefore, your example will fail to compile by C++03 rules and report correctly (that is, return `false`) in C++11. [This way](http://coliru.stacked-crooked.com/a/8eda5e72bd0d2681) works in both standards and should compile on old compilers, too, but sadly it tells us nothing about visibility of `value_type`. You can't have it both. – jrok Mar 05 '14 at 13:41
  • Now, you can combine the two ways of checking in C++11 to distinguish whether the member is there or not, and/or whether it is accessible. In C++03, it's impossible. – jrok Mar 05 '14 at 13:47

1 Answers1

0

As stated in the comments to the example you found:

"The proposed SFINAE works only if the method is public"

So, it will only detect public methods which should solve your question.

Community
  • 1
  • 1
Flovdis
  • 2,945
  • 26
  • 49
  • 1
    Is that only since C++11 ? [This post](http://stackoverflow.com/a/8984268/762488) seems to weight in that direction. – Antoine Mar 05 '14 at 12:18