Search code examples
c++visual-studiovisual-c++c++17tbb

TBB compiler error - 'my_task': references must be initialized


I use TBB at multiple places in my project. But it seems that since I update Visual Studio from 15.6.X (X beeing the latest version) to 15.7.1 I get a compiler error at several places, telling me

[...]tbb\task_group.h(94): error C2530: 'my_task': references must be initialized

Looking at the referenced code (tbb/task_group.h):

//! Base class for types that should not be assigned.
class no_assign {
    // Deny assignment
    void operator=( const no_assign& );
public:

#if __GNUC__
    //! Explicitly define default construction, because otherwise gcc issues gratuitous warning.
    no_assign() {}
#endif /* __GNUC__ */
};

//! Base class for types that should not be copied or assigned.
class no_copy: no_assign {
    //! Deny copy construction
    no_copy( const no_copy& );
public:
    //! Allow default construction
    no_copy() {}
};

// ...

class ref_count_guard : internal::no_copy {
    task& my_task;  // compiler error occurs here
public:
    ref_count_guard( task& t ) : my_task(t) {
        my_task.increment_ref_count();
    }
    ~ref_count_guard() {
        my_task.decrement_ref_count();
    }
};

I don't see why the compiler is complaining there, as the reference is initialized by the constructor. Finding the problem in my code is also not that easy, because the compiler error occurs in every single source file that uses TBB and I don't think I changed anything since my last successful compilation (besides updating VS).

One possibility that comes to my mind is related to this question. If msvc somehow inherits the base class constructors by default, a default constructor would be inherited explaining the error. But testing this scenario seems to disprove it (as the code compiles).

Why is msvc complaining here?

Update

This minimal example reproduces the error on my system:

#include <vector>
#include <tbb/tbb.h>
#include <tbb/flow_graph.h>       

void main()
{
    std::vector<int> src{1, 2, 3, 4, 5};
    tbb::parallel_for_each(src.begin(), src.end(), [](int) { });
}

Update 2

Looks like just including tbb/tbb.h causes the error to occur. I don't even need to call anything. Rebuilding tbb with the new compiler version didn't help either.

Edit

Cross issue on github.


Solution

  • This is a compiler bug when /permissive- option is used. It can be reproduced with the following code:

    struct U {
        template<typename T>
        void foo() {
            class A {
                int& iref;
            public:
                A(int& ir) : iref(ir) { }
            };
            int the_answer = 42;
            A a(the_answer);
        }
    };
    
    int main() {
        U u;
        u.foo<int>();
        return 0;
    }
    

    The code is perfectly valid, compliant C++. As you can see, the reference is explicitly initialized in the member initializer list of the constructor. Also this is seemingly a regression in VS, because at least the initial release of VS 2017 (15.0.something) compiles this code with /permissive-.