[cfe-dev] Possible bug with decltype and access modifer order

Richard Smith richard at metafoo.co.uk
Wed Jan 16 13:09:04 PST 2013


On Wed, Jan 16, 2013 at 8:06 AM, David Irvine <david.irvine at maidsafe.net> wrote:
> On Mon, Jan 14, 2013 at 9:52 PM, Richard Smith <richard at metafoo.co.uk>
> wrote:
>>
>> On Mon, Jan 14, 2013 at 1:01 PM, David Irvine <david.irvine at maidsafe.net>
>> wrote:
>>>
>>> Please see this stackoverflow question for an overview.
>>> http://stackoverflow.com/questions/14188535/clang-access-modifier-order-and-decltype
>>>
>>> The issue seems to be that the private members are not visible at
>>> compilation to the decltype call. This is a minimum example (from the
>>> question).  (I am the questioner in this case). This also seems to appear as
>>> a 'bug' in gcc but not msvc (12). I am not 100% convinced but cannot find in
>>> the standard why this will not work. I hope this helps.
>>>
>>>
>>> #include <future>
>>> #include <iostream>
>>> #include <thread>
>>> #include <vector>
>>>
>>> template <class T> T &self(T &t) { return t;  }
>>> template<typename T> struct Dependent {  };
>>>
>>> template<typename T>
>>> class Synchronised : Dependent<T>{
>>>  public:
>>>   explicit Synchronised(T t = T()) : t_(t) {}
>>>   template<typename Functor>
>>>   auto operator()(Functor functor) const
>>> ->decltype(functor(self(*this).t_)) {
>>>   //auto operator()(Functor functor) const ->decltype(functor(this->t_))
>>> {
>>>     std::lock_guard<std::mutex> lock(mutex_);
>>>     return functor(t_);
>>>   }
>>>  private:
>>>   mutable T t_;
>>>   mutable std::mutex mutex_;
>>> };
>>>
>>>
>>> int main() {
>>>
>>>     Synchronised<std::string> sync_string("Start\n");
>>>     std::vector<std::future<void>> futures;
>>> }
>>>
>>>
>>> Best Regards
>>> David Irvine
>>>
>>>
>>> maidsafe.net Limited is a limited liability company incorporated in
>>> Scotland with number SC297540. VAT Registered 889 0608 77. Registered
>>> Office: 72 Templehill, Troon, KA10 6BE.
>>> Telephone Scotland: +44 1292 750020.
>>>
>>>
>>> _______________________________________________
>>> cfe-dev mailing list
>>> cfe-dev at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>>>
>>
>> The instantiation of the template looks like this:
>>
>> template<> class Synchronised<std::string> : Dependent<std::string> {
>> public: explicit Synchronised(std::string t = std::string()) : t_(t) {}
>> template<typename Functor> auto operator()(Functor functor) const
>> ->decltype(functor(self(*this).t_)) { std::lock_guard<std::mutex>
>> lock(mutex_); return functor(t_); } private: mutable std::string t_; mutable
>> std::mutex mutex_; };
>>
>> This is ill-formed, since t_ has not yet been declared when the
>> trailing-return-type for operator() is processed. Per
>> [basic.lookup.classref]p2, the name t_ is looked up in the scope of class
>> Synchronized<std::string>. Per [basic.scope.class]p1, the name is not in
>> scope in the trailing-return-type, because it is not in the declarative
>> region following the name's point of declaration, and isn't a function body,
>> default argument, nor non-static data member initializer.
>
> Thanks very much for the answer
>
> Does this then indicate that auto func()-> decltype(stuff private_member) as
> a member function is always processed prior to the objects constructor
> initialises data members (private_member in this case). ?

It means that it's parsed where it appears in the class body (or at
least, it's allowed to be parsed then, see [basic.scope.class]p1 for
the details). The constructor is not relevant, but the location of the
declaration of the class member (relative to its use) is.

> If this is the case or there any other times where private should come
> before public accessors, if so and Chandler is listening then there is an
> interesting change to the Google style guide :-)

Well, the Google style guide does not allow trailing return types, nor
decltype...



More information about the cfe-dev mailing list